A framework to assess the potential ecosystem service gains from
restoration across five landscapes.
Purpose
Estimate the potential value of ecosystem services provision gain if
the target surface is distributed randomly across the intervention
areas.
The ecosystem data included here is derived from Chaplin-Kramer et.
al (2022) Mapping
the planet’s critical natural assets
Coastal Protection. Unitless measure, refers to a vulnerability
index. InVEST
Coastal Vulnerability Model
Nitrogen Export. Derived from the Nitrogen retention modeled
using the InVEST
Nutrient Delivery Ratio. Expressed in
kg/pixel/year
Sediment Retention. Derived using InVEST
SDR: Sediment Delivery Ration. Values in
ton/pixel/year
Pollination. Derived from InVEST
SDR: Pollinator Abundance Model. Units expressed on
equivalent people feed. More information in Chaplin-Kramer,
et al. 2022
- Nature Access represented as the number of people within 1 hour
travel of natural and semi-natural lands (Chaplin-Kramer et al,
2022).
-
Goals:
Identify High-Value Pixels: Focus restoration on areas where
ecosystem service gains are maximized.
Estimate Total Gains: If restoration is distributed randomly over
a target area, what is the expected ecosystem service value?
Represent uncertainty through confidence intervals and spatial
distributions of selected pixels.
Methods:
Assumptions
- All ecosystem services are equally valued.
- Value is a constant function of service quantity.
- Uniform likelihood of restoration across the intervention area
unless constrained by inputs (e.g., masks, distance).
- Independence of pixel values (no spatial autocorrelation considered
in sampling)
- Sampling provides a robust method for estimating random distribution
effects.
Approach:
- Normalize ecosystem service rasters to a 0-1 scale, add them, and
identify high-value areas.
- Randomly sample pixels to estimate service values under random
distribution scenarios, iterating multiple times for robust confidence
intervals. -Address spatial distribution issues (e.g., clustering) later
using additional weighting factors (e.g., downstream
beneficiaries).
Combined ES raster production:
Preliminar first step to deal with raster data sets representing
different variables.
Limitations: - Implicitly assumes equal importance
of ecosystem services. - May overemphasize areas with one dominant
service, especially pollination, which is contingent to agricultural
production. - Fails to account for geographically weighted factors, plan
to address.
Random Sampling:
Suited methodology when no location-based prioritization is assumed.
Repeated sampling process assuming Central Limit Theorem. Summarize
results with total estimated ES gains and confidence intervals.
1. Prepare Environemnt
Load libraries, functions and prepare template data
1.2 Load Templates
This loads and prepares template data used to align
# add backgrounds/templates to align
path_lc <- here('ESA_LC')
# load reclassified land cover map
tf <- file.path(path_lc, list.files(path_lc, pattern= "rec"))
lc <- lapply(tf,rast)
# create rcl matrix
rcl <- matrix(c(
0, Inf, 0 # Any value greater than 0 becomes 1
), ncol = 3, byrow = TRUE)
#create background pixels, subsitute all by 0
tmp <- lapply(lc, function(r){
r <- classify(r[[1]], rcl)
})
rm(lc)
3 Calculate Restoration Potential output.
tiffes <- file.path(here("restoration_combined"), list.files(paste0(here("restoration_combined")),pattern= 'ES_msk'))
baseES_m <- lapply(tiffes, rast)
tiffes
[1] "/home/jeronimo/OneDrive/WWF_nbs_op/restoration_combined/BRAZIL_ES_msk.tif"
[2] "/home/jeronimo/OneDrive/WWF_nbs_op/restoration_combined/MADAGASCAR_ES_msk.tif"
[3] "/home/jeronimo/OneDrive/WWF_nbs_op/restoration_combined/MEXICO_ES_msk.tif"
[4] "/home/jeronimo/OneDrive/WWF_nbs_op/restoration_combined/PERU_ES_msk.tif"
[5] "/home/jeronimo/OneDrive/WWF_nbs_op/restoration_combined/VIETNAM_ES_msk.tif"
3.1 Brazil Espiritu Santo
3.1.1 Prepare Template Brazil Espiritu Santo
This just create a background of Zeroes to use as template for
reprojecting (this is necessary because the access layer whic is on a
different crs. Not ideal, but need to move forward)
3.2 Madagascar (Not Necessary To Mask for te Interventions)
3.3 Yucatan
3.3.1 Prepare Template Yucatan
This just create a background of Zeroes to use as template for
reprojecting (this is necessary because the access layer whic is on a
different crs. Not ideal, but need to move forward)
3.3 Peru
4 Sampling and Extracting values
This will be dealt on a two part basis: 1.Identify the hectares that
yield the maximum aggregated restoration values withing the Griscom
restoration potential pixels. Contingent on the entry assumptions 2.
Model the estimated values of ES gains for the services based on a
random sampling. This second part has implicit a couple of
assumptions:
- We are not considering any spatial configuration (landscape metrics)
aspects affecting the total value
- Eventually, the model can be refined by incorporating additional
parameters (e.g minimum distance to boundaries, distance between points,
topography or inhabited areas (some of it is implicit in the input data,
but needs to be confirmed).
- Coastal risk protection only occurs at the coast, any random
sampling performed will haveto consider this. This can be adjusted using
weights.
This approach utilizes a stratified random sampling technique to
estimate the mean values of different bands in a multi-band raster
dataset. Stratified random sampling is a probability sampling method
where the population is divided into homogeneous subgroups called
strata, and random samples are taken from each stratum. In this case,
the strata are defined by the spatial extent of the raster dataset, and
the pixels within the raster represent the individual sampling
units.
Methodology
Define the Area of Interest: The first step is to define the area of
interest (AOI) within the raster dataset. This AOI represents the
spatial extent from which the samples will be drawn. In this specific
case, the AOI is defined as 30,000 hectares.
Calculate the Sample Size: Based on the resolution of the raster and
the desired AOI, the required number of pixels to be sampled is
calculated. This ensures that the total area covered by the sampled
pixels corresponds to the defined AOI.
Perform Stratified Random Sampling: The spatSample() function from
the terra package in R is used to perform stratified random sampling.
This function allows for random sampling of pixels within the defined
AOI, while also excluding pixels with “NA” values in all bands, ensuring
that only valid data points are included in the analysis.
Repeat Sampling: To reduce potential sampling bias and improve the
accuracy of the estimates, the random sampling process is repeated
multiple times (in this case, 30 times). This is analogous to the
concept of bootstrapping, where repeated sampling with replacement is
used to estimate the sampling distribution of a statistic.
Calculate Summary Statistics: For each repetition, the mean, standard
deviation, and 95% confidence intervals are calculated for each band in
the raster dataset. This provides a measure of the central tendency and
variability of the sampled data.
Synthesize Results: The results from all repetitions are combined to
calculate an overall mean and confidence interval for each band. This
provides a more robust estimate of the expected values, effectively
correcting for potential outliers and reducing the influence of
individual sample variations.
Theoretical Justification
The use of stratified random sampling is justified as it ensures that
the sample is representative of the entire population (i.e., all pixels
within the AOI). By dividing the population into strata and sampling
from each stratum, this method reduces the variability of the estimates
compared to simple random sampling. This is particularly important when
dealing with spatial data, where there may be inherent spatial
autocorrelation or heterogeneity.
The repeated sampling approach further enhances the robustness of the
estimates by providing a distribution of possible values. This allows
for the calculation of confidence intervals, which provide a measure of
the uncertainty associated with the estimates. By synthesizing the
results from multiple repetitions, the overall estimates are less
susceptible to the influence of individual sample variations and provide
a more accurate representation of the true population values.
References
Cochran, W. G. (1977). Sampling techniques (3rd ed.). John Wiley
& Sons. Lohr, S. L. (2010). Sampling: Design and analysis (2nd ed.).
Brooks/Cole. 1
1. Bivand, R. S., Pebesma, E. J., & Gómez-Rubio, V. (2013). Applied
spatial data analysis with R (2nd ed.). Springer.
4.1 Espirito Santo
4.1.1 Prepare Data Esp Santo.
Align and resampe all the raster datasets to the same crs and
origin.
4.1.2 Run Sampling and Syntetize results - Espirito Santo
Here, we are sampling the data for obtain estimate of the expected
restoration gains assuming randomly selected pixels extracted form the
potential restoration areas. Again, some assumptions will have to be
reviewed, but this is an initial assessment. The targeted intervention
area is 30.200 ha.
4.1.3 Plot Results Espirito Santo

4.2 Yucatan
The approach is the same as in Brazil. Two main intervention areas
were used tro build the final polygon: the jaguar corridor and ### 4.2.1
Prepare Data Yucatan. Align and resample all the raster bands to the ame
crs and origin.
4.1.2 Run Sampling and Synthetize results - Yucatan
4.1.3 . Plot Results Yucatan

Next Steps:
Run the Analysis for Madre de Dios, incorpporate
beneficiaries/population related data, as the target metric is not the
sum of the values.
LS0tCnRpdGxlOiAiRGFUYSBQcmVwYXJhdGlvbiBOQlMiCm91dHB1dDoKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKICBodG1sX2RvY3VtZW50OgogICAgZGZfcHJpbnQ6IHBhZ2VkCmVkaXRvcl9vcHRpb25zOgogIG1hcmtkb3duOgogICAgd3JhcDogNzIKLS0tCgoKCkEgZnJhbWV3b3JrIHRvIGFzc2VzcyB0aGUgcG90ZW50aWFsIGVjb3N5c3RlbSBzZXJ2aWNlIGdhaW5zIGZyb20gcmVzdG9yYXRpb24gYWNyb3NzIGZpdmUgbGFuZHNjYXBlcy4KCiMgUHVycG9zZQoKRXN0aW1hdGUgdGhlIHBvdGVudGlhbCB2YWx1ZSBvZiBlY29zeXN0ZW0gc2VydmljZXMgcHJvdmlzaW9uIGdhaW4gIGlmIHRoZSB0YXJnZXQgc3VyZmFjZSBpcyBkaXN0cmlidXRlZCByYW5kb21seSBhY3Jvc3MgdGhlIGludGVydmVudGlvbiBhcmVhcy4KCgpUaGUgZWNvc3lzdGVtIGRhdGEgaW5jbHVkZWQgaGVyZSBpcyBkZXJpdmVkIGZyb20gQ2hhcGxpbi1LcmFtZXIgZXQuIGFsICgyMDIyKSBbKipNYXBwaW5nIHRoZSBwbGFuZXTigJlzIGNyaXRpY2FsIG5hdHVyYWwgYXNzZXRzKipdKGh0dHBzOi8vd3d3Lm5hdHVyZS5jb20vYXJ0aWNsZXMvczQxNTU5LTAyMi0wMTkzNC01KQoKCjEuIENvYXN0YWwgUHJvdGVjdGlvbi4gVW5pdGxlc3MgbWVhc3VyZSwgcmVmZXJzIHRvIGEgdnVsbmVyYWJpbGl0eSBpbmRleC4gWyoqSW5WRVNUIENvYXN0YWwgVnVsbmVyYWJpbGl0eSBNb2RlbCoqXShodHRwczovL3N0b3JhZ2UuZ29vZ2xlYXBpcy5jb20vcmVsZWFzZXMubmF0dXJhbGNhcGl0YWxwcm9qZWN0Lm9yZy9pbnZlc3QtdXNlcmd1aWRlL2xhdGVzdC9lbi9jb2FzdGFsX3Z1bG5lcmFiaWxpdHkuaHRtbCkKCjIuIE5pdHJvZ2VuIEV4cG9ydC4gRGVyaXZlZCBmcm9tIHRoZSBOaXRyb2dlbiByZXRlbnRpb24gbW9kZWxlZCB1c2luZyB0aGUgWyoqSW5WRVNUIE51dHJpZW50IERlbGl2ZXJ5IFJhdGlvKipdKGh0dHA6Ly9kYXRhLm5hdHVyYWxjYXBpdGFscHJvamVjdC5vcmcvaW52ZXN0LXJlbGVhc2VzLzMuNS4wL3VzZXJndWlkZS9uZHIuaHRtbCkuIEV4cHJlc3NlZCBpbiBrZy9waXhlbC95ZWFyCgozLiBTZWRpbWVudCBSZXRlbnRpb24uIERlcml2ZWQgdXNpbmcgWyoqSW5WRVNUIFNEUjogU2VkaW1lbnQgRGVsaXZlcnkgUmF0aW9uKipdKGh0dHBzOi8vc3RvcmFnZS5nb29nbGVhcGlzLmNvbS9yZWxlYXNlcy5uYXR1cmFsY2FwaXRhbHByb2plY3Qub3JnL2ludmVzdC11c2VyZ3VpZGUvbGF0ZXN0L2VuL3Nkci5odG1sKS4gVmFsdWVzIGluIHRvbi9waXhlbC95ZWFyCgo0LiBQb2xsaW5hdGlvbi4gRGVyaXZlZCBmcm9tIFsqKkluVkVTVCBTRFI6IFBvbGxpbmF0b3IgQWJ1bmRhbmNlIE1vZGVsKipdKGh0dHBzOi8vc3RvcmFnZS5nb29nbGVhcGlzLmNvbS9yZWxlYXNlcy5uYXR1cmFsY2FwaXRhbHByb2plY3Qub3JnL2ludmVzdC11c2VyZ3VpZGUvbGF0ZXN0L2VuL2Nyb3Bwb2xsaW5hdGlvbi5odG1sKS4gVW5pdHMgZXhwcmVzc2VkIG9uICplcXVpdmFsZW50IHBlb3BsZSBmZWVkKi4KIE1vcmUgaW5mb3JtYXRpb24gaW4gWyoqQ2hhcGxpbi1LcmFtZXIsIGV0IGFsLiAyMDIyKipdKGh0dHBzOi8vc3RhdGljLWNvbnRlbnQuc3ByaW5nZXIuY29tL2VzbS9hcnQlM0ExMC4xMDM4JTJGczQxNTU5LTAyMi0wMTkzNC01L01lZGlhT2JqZWN0cy80MTU1OV8yMDIyXzE5MzRfTU9FU00xX0VTTS5wZGYpCgo1LiBOYXR1cmUgQWNjZXNzIHJlcHJlc2VudGVkIGFzICp0aGUgbnVtYmVyIG9mIHBlb3BsZSB3aXRoaW4gMSBob3VyIHRyYXZlbCBvZiBuYXR1cmFsIGFuZCBzZW1pLW5hdHVyYWwgbGFuZHMqIChDaGFwbGluLUtyYW1lciBldCBhbCwgMjAyMikuCjogCiMgR29hbHM6CgotIElkZW50aWZ5IEhpZ2gtVmFsdWUgUGl4ZWxzOiBGb2N1cyByZXN0b3JhdGlvbiBvbiBhcmVhcyB3aGVyZSBlY29zeXN0ZW0gc2VydmljZSBnYWlucyBhcmUgbWF4aW1pemVkLgotIEVzdGltYXRlIFRvdGFsIEdhaW5zOiBJZiByZXN0b3JhdGlvbiBpcyBkaXN0cmlidXRlZCByYW5kb21seSBvdmVyIGEgdGFyZ2V0IGFyZWEsIHdoYXQgaXMgdGhlIGV4cGVjdGVkIGVjb3N5c3RlbSBzZXJ2aWNlIHZhbHVlPwoKLSBSZXByZXNlbnQgdW5jZXJ0YWludHkgdGhyb3VnaCBjb25maWRlbmNlIGludGVydmFscyBhbmQgc3BhdGlhbCBkaXN0cmlidXRpb25zIG9mIHNlbGVjdGVkIHBpeGVscy4KCiMgTWV0aG9kczoKCiMjIEFzc3VtcHRpb25zCgotIEFsbCBlY29zeXN0ZW0gc2VydmljZXMgYXJlIGVxdWFsbHkgdmFsdWVkLgotIFZhbHVlIGlzIGEgY29uc3RhbnQgZnVuY3Rpb24gb2Ygc2VydmljZSBxdWFudGl0eS4KLSBVbmlmb3JtIGxpa2VsaWhvb2Qgb2YgcmVzdG9yYXRpb24gYWNyb3NzIHRoZSBpbnRlcnZlbnRpb24gYXJlYSB1bmxlc3MgY29uc3RyYWluZWQgYnkgaW5wdXRzIChlLmcuLCBtYXNrcywgZGlzdGFuY2UpLgotIEluZGVwZW5kZW5jZSBvZiBwaXhlbCB2YWx1ZXMgKG5vIHNwYXRpYWwgYXV0b2NvcnJlbGF0aW9uIGNvbnNpZGVyZWQgaW4gc2FtcGxpbmcpCi0gU2FtcGxpbmcgcHJvdmlkZXMgYSByb2J1c3QgbWV0aG9kIGZvciBlc3RpbWF0aW5nIHJhbmRvbSBkaXN0cmlidXRpb24gZWZmZWN0cy4KCiMgQXBwcm9hY2g6CgotIE5vcm1hbGl6ZSBlY29zeXN0ZW0gc2VydmljZSByYXN0ZXJzIHRvIGEgMC0xIHNjYWxlLCBhZGQgdGhlbSwgYW5kIGlkZW50aWZ5IGhpZ2gtdmFsdWUgYXJlYXMuCi0gUmFuZG9tbHkgc2FtcGxlIHBpeGVscyB0byBlc3RpbWF0ZSBzZXJ2aWNlIHZhbHVlcyB1bmRlciByYW5kb20gZGlzdHJpYnV0aW9uIHNjZW5hcmlvcywgaXRlcmF0aW5nIG11bHRpcGxlIHRpbWVzIGZvciByb2J1c3QgY29uZmlkZW5jZSBpbnRlcnZhbHMuCi1BZGRyZXNzIHNwYXRpYWwgZGlzdHJpYnV0aW9uIGlzc3VlcyAoZS5nLiwgY2x1c3RlcmluZykgbGF0ZXIgdXNpbmcgYWRkaXRpb25hbCB3ZWlnaHRpbmcgZmFjdG9ycyAoZS5nLiwgZG93bnN0cmVhbSBiZW5lZmljaWFyaWVzKS4KCgojIyBDb21iaW5lZCBFUyByYXN0ZXIgcHJvZHVjdGlvbjoKClByZWxpbWluYXIgZmlyc3Qgc3RlcCB0byBkZWFsIHdpdGggcmFzdGVyIGRhdGEgc2V0cyByZXByZXNlbnRpbmcgZGlmZmVyZW50IHZhcmlhYmxlcy4KCioqTGltaXRhdGlvbnM6KioKLSBJbXBsaWNpdGx5IGFzc3VtZXMgZXF1YWwgaW1wb3J0YW5jZSBvZiBlY29zeXN0ZW0gc2VydmljZXMuCi0gTWF5IG92ZXJlbXBoYXNpemUgYXJlYXMgd2l0aCBvbmUgZG9taW5hbnQgc2VydmljZSwgZXNwZWNpYWxseSBwb2xsaW5hdGlvbiwgd2hpY2ggaXMgY29udGluZ2VudCB0byBhZ3JpY3VsdHVyYWwgcHJvZHVjdGlvbi4KLSBGYWlscyB0byBhY2NvdW50IGZvciBnZW9ncmFwaGljYWxseSB3ZWlnaHRlZCBmYWN0b3JzLCBwbGFuIHRvIGFkZHJlc3MuCgojIyBSYW5kb20gU2FtcGxpbmc6CgpTdWl0ZWQgbWV0aG9kb2xvZ3kgd2hlbiBubyBsb2NhdGlvbi1iYXNlZCBwcmlvcml0aXphdGlvbiBpcyBhc3N1bWVkLgpSZXBlYXRlZCAgc2FtcGxpbmcgcHJvY2VzcyAgYXNzdW1pbmcgIENlbnRyYWwgTGltaXQgVGhlb3JlbS4KU3VtbWFyaXplIHJlc3VsdHMgd2l0aCB0b3RhbCBlc3RpbWF0ZWQgRVMgZ2FpbnMgYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWxzLgoKCgojIDEuIFByZXBhcmUgRW52aXJvbmVtbnQgCgpMb2FkIGxpYnJhcmllcywgZnVuY3Rpb25zIGFuZCBwcmVwYXJlIHRlbXBsYXRlIGRhdGEgCgpgYGB7ciBhbGlnbiBsaXN0IG9mIHJhc3RlcnMsIGV2YWw9VFJVRSwgaW5jbHVkZT1GQUxTRX0KcGFja3MgPC0gYygndGVycmEnLCAncHVycnInLCAnbGFuZHNjYXBlbWV0cmljcycsICdzZicsJ2RwbHlyJywKICAgICAgICAgICAnaGVyZScsICdnZGFsVXRpbGl0aWVzJywgJ2pzb25saXRlJywgJ2RldnRvb2xzJywgJ3N0cmluZ3InLAogICAgICAgICAgICdwYXJhbGxlbCcsICdkcGx5cicsICd0aWR5cicsICdnZ3Bsb3QyJywgJ2phbml0b3InLCAnZm9yY2F0cycsICdmb3JlaWduJykKc2FwcGx5KHBhY2tzLCByZXF1aXJlLCBjaGFyYWN0ZXIub25seSA9IFRSVUUsIHF1aWV0bHk9VFJVRSkKcm0ocGFja3MpCmFsaWduX3Jhc3RlcnMgPC0gZnVuY3Rpb24ocmFzdGVyX2xpc3QsIHRlbXBsYXRlLCByZXNhbXBsZV9tZXRob2QgPSAiYmlsaW5lYXIiKSB7CiAgbGFwcGx5KHJhc3Rlcl9saXN0LCBmdW5jdGlvbihyKSB7CiAgICBpZiAoIWNvbXBhcmVHZW9tKHIsIHRlbXBsYXRlLCBzdG9wT25FcnJvciA9IEZBTFNFKSkgewogICAgICBtZXNzYWdlKCJBbGlnbmluZyByYXN0ZXI6ICIsIG5hbWVzKHIpKQogICAgICAjIFJlc2FtcGxlIHRvIGFsaWduIHdpdGggdGhlIHRlbXBsYXRlCiAgICAgIHJlc2FtcGxlKHIsIHRlbXBsYXRlLCBtZXRob2QgPSByZXNhbXBsZV9tZXRob2QpCiAgICB9IGVsc2UgewogICAgICAjIFJldHVybiByYXN0ZXIgYXMgaXMgaWYgYWxyZWFkeSBhbGlnbmVkCiAgICAgIG1lc3NhZ2UoIlJhc3RlciBhbHJlYWR5IGFsaWduZWQ6ICIsIG5hbWVzKHIpKQogICAgICByCiAgICB9CiAgfSkKfQoKcHJvY2Vzc19yYXN0ZXJzIDwtIGZ1bmN0aW9uKG5lc3RlZF9saXN0LCB0ZW1wbGF0ZXMsIHJlc2FtcGxlX21ldGhvZCA9ICJiaWxpbmVhciIpIHsKICBsYXBwbHkoc2VxX2Fsb25nKG5lc3RlZF9saXN0KSwgZnVuY3Rpb24oaSkgewogICAgIyBBbGlnbiBhbGwgcmFzdGVycyBpbiB0aGUgc3VibGlzdCB0byB0aGUgdGVtcGxhdGUKICAgIGFsaWduZWQgPC0gbGFwcGx5KG5lc3RlZF9saXN0W1tpXV0sIGZ1bmN0aW9uKHIpIHsKICAgICAgaWYgKCFjb21wYXJlR2VvbShyLCB0ZW1wbGF0ZXNbW2ldXSwgc3RvcE9uRXJyb3IgPSBGQUxTRSkpIHsKICAgICAgICBtZXNzYWdlKCJBbGlnbmluZyByYXN0ZXI6ICIsIG5hbWVzKHIpKQogICAgICAgIHJlc2FtcGxlKHIsIHRlbXBsYXRlc1tbaV1dLCBtZXRob2QgPSByZXNhbXBsZV9tZXRob2QpCiAgICAgIH0gZWxzZSB7CiAgICAgICAgbWVzc2FnZSgiUmFzdGVyIGFscmVhZHkgYWxpZ25lZDogIiwgbmFtZXMocikpCiAgICAgICAgcgogICAgICB9CiAgICB9KQogICAgIyBTdGFjayBhbGwgYWxpZ25lZCByYXN0ZXJzIGludG8gYSBzaW5nbGUgbXVsdGliYW5kIFNwYXRSYXN0ZXIKICAgIHN0YWNrZWQgPC0gZG8uY2FsbChjLCBhbGlnbmVkKQogICAgCiAgIHRtcCAjIE1lcmdlIHRoZSBzdGFja2VkIHJhc3RlciB3aXRoIHRoZSBjb3JyZXNwb25kaW5nIHRlbXBsYXRlIHJhc3RlcgogICAgbWVyZ2VkIDwtIG1lcmdlKHN0YWNrZWQsIHRlbXBsYXRlc1tbaV1dKQogICAgCiAgICAjIFN1bSB0aGUgbGF5ZXJzIG9mIHRoZSBtZXJnZWQgcmFzdGVyCiAgICBhcHAobWVyZ2VkLCBzdW0pCiAgfSkKfQpub3JtYWxpemVfcmFzdGVyIDwtIGZ1bmN0aW9uKHIpIHsKICBtaW5fdmFsIDwtIG1pbih2YWx1ZXMociksIG5hLnJtID0gVFJVRSkKICBtYXhfdmFsIDwtIG1heCh2YWx1ZXMociksIG5hLnJtID0gVFJVRSkKICAociAtIG1pbl92YWwpIC8gKG1heF92YWwgLSBtaW5fdmFsKQp9Cgpwcm9jZXNzX2ludGVydmVudGlvbl9hcmVhIDwtIGZ1bmN0aW9uKHJhc3Rlcl9saXN0KSB7CiAgIyBOb3JtYWxpemUgZWFjaCByYXN0ZXIgaW4gdGhlIGxpc3QKICBub3JtYWxpemVkX3Jhc3RlcnMgPC0gbGFwcGx5KHJhc3Rlcl9saXN0LCBub3JtYWxpemVfcmFzdGVyKQogICMgQ29tYmluZSB0aGUgbm9ybWFsaXplZCByYXN0ZXJzIGJ5IHN1bW1pbmcgdGhlbQogIGNvbWJpbmVkX3Jhc3RlciA8LSBkby5jYWxsKHN1bSwgbm9ybWFsaXplZF9yYXN0ZXJzKQogIHJldHVybihjb21iaW5lZF9yYXN0ZXIpCn0KYGBgCgojIyAxLjIgTG9hZCBUZW1wbGF0ZXMKClRoaXMgbG9hZHMgYW5kIHByZXBhcmVzIHRlbXBsYXRlIGRhdGEgdXNlZCB0byBhbGlnbgpgYGB7ciBjcmVhdGUgdG1wfQpsaWJyYXJ5KGhlcmUpCiMgYWRkIGJhY2tncm91bmRzL3RlbXBsYXRlcyB0byBhbGlnbiAKcGF0aF9sYyA8LSBoZXJlKCdFU0FfTEMnKSAKIyBsb2FkIHJlY2xhc3NpZmllZCBsYW5kIGNvdmVyIG1hcAp0ZiA8LSBmaWxlLnBhdGgocGF0aF9sYywgbGlzdC5maWxlcyhwYXRoX2xjLCBwYXR0ZXJuPSAicmVjIikpCmxjIDwtIGxhcHBseSh0ZixyYXN0KQojIGNyZWF0ZSByY2wgbWF0cml4CnJjbCA8LSBtYXRyaXgoYygKICAwLCBJbmYsIDAgICAjIEFueSB2YWx1ZSBncmVhdGVyIHRoYW4gMCBiZWNvbWVzIDEKKSwgbmNvbCA9IDMsIGJ5cm93ID0gVFJVRSkKCiNjcmVhdGUgYmFja2dyb3VuZCBwaXhlbHMsIHN1YnNpdHV0ZSBhbGwgYnkgMAp0bXAgPC0gbGFwcGx5KGxjLCBmdW5jdGlvbihyKXsKICByIDwtIGNsYXNzaWZ5KHJbWzFdXSwgcmNsKQp9KQoKcm0obGMpCmBgYAoKCiMgMiBFeHRyYWN0IHRoZSBkYXRhCgojIyAyLjEgTGlzdCB0aGUgUmVzdG9yYXRpb24gTGF5ZXJzIApgYGB7ciBzZWxlY3QgY29uc2VydmF0aW9uIGRhdGF9CiNSZXN0b3JhdGlvbjoKdGlmZmVzIDwtIGZpbGUucGF0aChoZXJlKCJjcm9wcGVkX3Jhc3Rlcl9kYXRhIiApLCBsaXN0LmZpbGVzKHBhc3RlMChoZXJlKCJjcm9wcGVkX3Jhc3Rlcl9kYXRhIikpLHBhdHRlcm49ICcudGlmJCcpKQp0aWZmZXMgPC0gdGlmZmVzW2MoMTo1LDUxOjU1LDcxOjc1LDgxOjkwLDEwNjoxMTApXQpgYGAKCiMjIDIuMiBOb3JtYWxpemUgYW5kIGNvbWJpbmUgZGF0YSBsYXllcnMKClRoZSBjb21iaW5lZCByYXN0ZXIgaXMgYSBwcm94eSBmb3IgdGhlIHRvdGFsIEVTIHByb3ZpZGVkKHdpdGggc29tZSBhc3N1bXB0aW9ucyB0aGF0IG5lZWQgdG8gYmUgZXZlbnR1YWxseSByZXZpZXdlZCBhbmQgcmVmaW5lZCkuCgpgYGB7ciBhcHBseSBtYXNrIEFPSSBBUCwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KCiMgU3RlcCAxOiBFeHRyYWN0IGZpbGUgbmFtZXMsIHByb2R1Y3QgbmFtZXMsIGFuZCBjb3VudHJ5IG5hbWVzCmZpbGVfbmFtZXMgPC0gYmFzZW5hbWUodGlmZmVzKSAgIyBFeHRyYWN0IGZpbGUgbmFtZXMgZnJvbSBwYXRocwoKIyBFeHRyYWN0IHByb2R1Y3QgbmFtZXMgYW5kIGNvdW50cnkgbmFtZXMKcHJvZHVjdF9uYW1lcyA8LSBzdWIoIl9bQS1aXStcXC50aWYkIiwgIiIsIGZpbGVfbmFtZXMpICAjIFJlbW92ZSAiX0NPVU5UUlkudGlmIiB0byBnZXQgcHJvZHVjdCBuYW1lCmNvdW50cnlfbmFtZXMgPC0gc3ViKCIuKl8oLio/KVxcLnRpZiQiLCAiXFwxIiwgZmlsZV9uYW1lcykgICMgRXh0cmFjdCBjb3VudHJ5IG5hbWUgZnJvbSBmaWxlIG5hbWUKCiMgU3RlcCAyOiBDcmVhdGUgYSBkYXRhZnJhbWUgdG8gb3JnYW5pemUgdGhlIGluZm9ybWF0aW9uCmZpbGVfaW5mbyA8LSBkYXRhLmZyYW1lKAogIEZpbGVQYXRoID0gdGlmZmVzLAogIFByb2R1Y3QgPSBwcm9kdWN0X25hbWVzLAogIENvdW50cnkgPSBjb3VudHJ5X25hbWVzLAogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQopCgojIFN0ZXAgMzogU29ydCB0aGUgZGF0YWZyYW1lIGJ5IENvdW50cnkgZmlyc3QsIHRoZW4gYnkgUHJvZHVjdApmaWxlX2luZm8gPC0gZmlsZV9pbmZvICU+JQogIGFycmFuZ2UoQ291bnRyeSwgUHJvZHVjdCkKCiMgU3RlcCA0OiBFeHRyYWN0IHRoZSBzb3J0ZWQgZmlsZSBwYXRocwp0aWZmZXMgPC0gZmlsZV9pbmZvJEZpbGVQYXRoCgpiYXNlRVMgPC0gbGFwcGx5KHRpZmZlcywgcmFzdCkKYmFzZUVTIDwtIGxhcHBseShiYXNlRVMsIGZ1bmN0aW9uKHIpewogIHIgPC0gbm9ybWFsaXplX3Jhc3RlcihyKQp9KQoKIyBzZXQgdGhlIG51bWJlciBvZiBkaWZmZXJlbnQgcHJvZHVjdHMgdG8gc3BsaXQgdGhlIGxpc3QgCm51bSA8LSBsZW5ndGgodW5pcXVlKHByb2R1Y3RfbmFtZXMpKQojIHNwbGl0IGFnYWluIHRvIGhhdmUgbmVzdGVkIGxpc3RzCmJhc2VFUyA8LSBzcGxpdChiYXNlRVMsIHJlcCgxOmxlbmd0aChuYW0pLCBlYWNoID0gbnVtKSkKCiMgYWxpZ24sIGFkZCBiYWNrZ3JvdW5kIGFuZCBzdW0gYWxsIHRoZSB2YWx1ZXMKYmFzZUVTIDwtIHByb2Nlc3NfcmFzdGVycyhiYXNlRVMsdG1wLCByZXNhbXBsZV9tZXRob2QgPSAiYmlsaW5lYXIiKQptYXAoMTpsZW5ndGgoYmFzZUVTKSwgZnVuY3Rpb24oeCkgd3JpdGVSYXN0ZXIoYmFzZUVTW1t4XV0sIHBhc3RlMChoZXJlKCJyZXN0b3JhdGlvbl9jb21iaW5lZCIpLCcvJywgdW5pcXVlKGNvdW50cnlfbmFtZXMpW1t4XV0sICdfRVNfc3VtLnRpZicpKSkKYGBgCgoKIyMgMi4zIExvYWQgQWRqdXN0ZWQgR3Jpc2NvbSBSZXN0b3JhdGlvbiBEYXRhIGFuZCBhcHBseSBtYXNrCgpVc2UgdGhlIGFkanVzdGVkIEdyaXNjb20gcmVzdG9yYXRpb24gZGF0YSAoZGVhbHMgd2l0aCBwaXhlbCB2YWx1ZXMgZW5jb2RpbmcgaXNzdWVzIGluIHRoZSBvcmlnaW5hbCBkYXRhLCBoYWQgdG8gZ2V0IHRoZSBtZXRhZGFkYXRhIGZvciB0aGF0KS4gV2UgYXBwbHkgdGhpcyBtYXNrIHRvIGlzb2xhdGUgb25seSB0aGUgcGl4ZWxzIHRoYXQgaGF2ZSBiZWVuIGlkZW50aWZpZWQgYXMgUmVzdG9yYXRpb24gUG90ZW50aWFsIGluIEdyaXNjb20ncyAgRGF0YXNldCBvbiBbR2xvYmFsIHByaW9yaXR5IGFyZWFzIGZvciBlY29zeXN0ZW0KcmVzdG9yYXRpb25dKGh0dHBzOi8vd3d3LmtzZmlyZS5vcmcvd29vZHlfZW5jcm9hY2htZW50L2RvY3VtZW50cy9HbG9iYWwlMjBwcmlvcml0eSUyMGFyZWFzJTIwb2YlMjBlY29zeXRlbSUyMHJlc3RvcmF0aW9uLnBkZikuCgoKCmBgYHtyIGxvYWQgR3Jpc2NvbXMgZGF0YSwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KIyBMb2FkIEdyaXNjb20gRGF0YQp0aWZmZXMgPC0gZmlsZS5wYXRoKGhlcmUoIlJlc3RvcmF0aW9uX0dyaXNjb20iKSwgbGlzdC5maWxlcyhwYXN0ZTAoaGVyZSgiUmVzdG9yYXRpb25fR3Jpc2NvbSIpKSxwYXR0ZXJuPSAncmVjJykpCgpwYV9yYyA8LSBsYXBwbHkodGlmZmVzLHJhc3QpCgpiYXNlRVNfbSA8LSBtYXAyKAogIGJhc2VFUywgCiAgcGFfcmMsIAogIGZ1bmN0aW9uKHJzdCwgbXNrKSB7CiAgICAjIEFwcGx5IG1hc2sgdG8gZWFjaCByYXN0ZXIgaW4gdGhlIHN1Ymxpc3QgdXNpbmcgdGhlIGNvcnJlc3BvbmRpbmcgY291bnRyeSB2ZWN0b3IKICAgIG1hc2socnN0LCBtc2ssIG1hc2t2YWx1ZT0wKQogIH0KKQptYXAoMTpsZW5ndGgoYmFzZUVTKSwgZnVuY3Rpb24oeCkgd3JpdGVSYXN0ZXIoYmFzZUVTX21bW3hdXSwgcGFzdGUwKGhlcmUoInJlc3RvcmF0aW9uX2NvbWJpbmVkIiksJy8nLCB1bmlxdWUoY291bnRyeV9uYW1lcylbW3hdXSwgJ19FU19tc2sudGlmJyksIG92ZXJ3cml0ZT1UKSkKYGBgCgohW0ludGVydmVudGlvbiBBcmVhcyAmIENvbWJpZW5kIFJlc3RvcmF0aW9uIFBvdGVudGlhbF0oL2hvbWUvamVyb25pbW8vT25lRHJpdmUvV1dGX25ic19vcC9vdXRwdXRfbWFwcy9tYXBzX2ludGVydmVudGlvbnMucG5nKQoKCiMgMyBDYWxjdWxhdGUgUmVzdG9yYXRpb24gUG90ZW50aWFsIG91dHB1dC4KCgpgYGB7ciBsb2FkIGludGV2ZW50aW9uIGRhdGF9CnRpZmZlcyA8LSBmaWxlLnBhdGgoaGVyZSgicmVzdG9yYXRpb25fY29tYmluZWQiKSwgbGlzdC5maWxlcyhwYXN0ZTAoaGVyZSgicmVzdG9yYXRpb25fY29tYmluZWQiKSkscGF0dGVybj0gJ0VTX21zaycpKQpiYXNlRVNfbSA8LSBsYXBwbHkodGlmZmVzLCByYXN0KQp0aWZmZXMKYGBgCgojIyAzLjEgQnJhemlsIEVzcGlyaXR1IFNhbnRvCmBgYHtyIGJyYXppbCBpbnRlcnZlbnRpb24gLCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpwb2x5IDwtIHN0X3JlYWQoaGVyZSgiSW50ZXJ2ZW50aW9ucyIsICJCcmF6aWxfaW50X2FyZWFzIiwgIkVzcGlyaXRvX1NhbnRvX0FsYmVycy5zaHAiKSkKcG9sX3dncyA8LSBzdF90cmFuc2Zvcm0ocG9seSwgY3JzPWNycyhiYXNlRVNfbVtbMV1dKSkKc2Vydl9icmEgPC0gYmFzZUVTX21bWzFdXSAlPiUgY3JvcChwb2xfd2dzKSAlPiUgbWFzayhwb2xfd2dzKQpzZXJ2X2JyYSA8LSBwcm9qZWN0KHNlcnZfYnJhLCBjcnMocG9seSksIG1ldGhvZD0nY3ViaWMnKQpyZXN0X3NwIDwtIGNyb3AocGFfcmNbWzFdXSwgcG9sX3dncykKcmVzdF9zcCA8LSBtYXNrKHJlc3Rfc3AscG9sX3dncykKd3JpdGVSYXN0ZXIoc2Vydl9icmEsIGhlcmUoIkludGVydmVudGlvbnMiLCAiQnJhemlsX2ludGVydmVudGlvbiIsICJlc3Bfc2FudG9fcmVzdC50aWYiKSxvdmVyd3JpdGU9VFJVRSkKd3JpdGVSYXN0ZXIocmVzdF9zcCwgaGVyZSgiSW50ZXJ2ZW50aW9ucyIsICJCcmF6aWxfaW50ZXJ2ZW50aW9uIiwgIlNTX2dyaXNjb20udGlmIiksIG92ZXJ3cml0ZT1UUlVFKQoKYGBgCgojIyMgMy4xLjEgUHJlcGFyZSBUZW1wbGF0ZSBCcmF6aWwgRXNwaXJpdHUgU2FudG8KVGhpcyBqdXN0IGNyZWF0ZSBhIGJhY2tncm91bmQgb2YgWmVyb2VzIHRvIHVzZSBhcyB0ZW1wbGF0ZSBmb3IgcmVwcm9qZWN0aW5nICh0aGlzIGlzIG5lY2Vzc2FyeSBiZWNhdXNlIHRoZSBhY2Nlc3MgbGF5ZXIgd2hpYyBpcyBvbiBhIGRpZmZlcmVudCBjcnMuIE5vdCBpZGVhbCwgYnV0IG5lZWQgdG8gbW92ZSBmb3J3YXJkKQpgYGB7ciBicmF6aWwgaW50ZXJ2ZW50aW9uIDEsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnBvbHkgPC0gc3RfcmVhZChoZXJlKCJJbnRlcnZlbnRpb25zIiwgIkJyYXppbF9pbnRfYXJlYXMiLCAiRXNwaXJpdG9fU2FudG9fQWxiZXJzLnNocCIpKQpwb2xfd2dzIDwtIHN0X3RyYW5zZm9ybShwb2x5LCBjcnM9Y3JzKHRtcFtbMV1dKSkKc2Vydl9icmEgPC0gdG1wW1sxXV0gJT4lIGNyb3AocG9sX3dncykgJT4lIG1hc2socG9sX3dncykKc2Vydl9icmEgPC0gcHJvamVjdChzZXJ2X2JyYSwgY3JzKHBvbHkpLCByZXM9MzApCndyaXRlUmFzdGVyKHNlcnZfYnJhLCBoZXJlKCJJbnRlcnZlbnRpb25zIiwgIkJyYXppbF9pbnRlcnZlbnRpb24iLCAiZXNwX3NhbnRvX2JrZy50aWYiKSxvdmVyd3JpdGU9VFJVRSkKCmBgYAoKIyMgMy4yIE1hZGFnYXNjYXIgKE5vdCBOZWNlc3NhcnkgVG8gTWFzayBmb3IgdGUgSW50ZXJ2ZW50aW9ucykKYGBge3IgTWFkYWdhc2NhciBpbnRlcnZlbnRpb24gMSwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0KcG9seSA8LSBzdF9yZWFkKGhlcmUoIkludGVydmVudGlvbnMiLCAiTWV4X2ludGVydmVudGlvbiIsIm1leF9pbnRlcnZlbnRpb24yLmdlb2pzb24iKSkKCnBvbF93Z3MgPC0gc3RfdHJhbnNmb3JtKHBvbHksIGNycz1jcnMoYmFzZUVTX21bWzNdXSkpCnNlcnZfbWRnIDwtIGJhc2VFU19tW1szXV0gCnNlcnZfbWRnIDwtIHByb2plY3Qoc2Vydl9tZGcsIGNycyhwb2xfd2dzKSwgbWV0aG9kPSdjdWJpYycpCnJlc3RfbWRnIDwtIGNyb3AocGFfcmNbWzNdXSwgcG9sX3dncykKcmVzdF9zcCA8LSBtYXNrKHJlc3Rfc3AscG9sX3dncykKd3JpdGVSYXN0ZXIoc2Vydl9tZGcsIGhlcmUoIkludGVydmVudGlvbnMiLCAiTWRnX2ludGVydmVudGlvbiIsICJtZGdfaW50X3Jlc3QudGlmIikpCndyaXRlUmFzdGVyKHJlc3Rfc3AsIGhlcmUoIkludGVydmVudGlvbnMiLCAiTWRnX2ludGVydmVudGlvbiIsICJtZGdfZ3Jpc2NvbS50aWYiKSkKCmBgYAoKIyMgMy4zICBZdWNhdGFuCmBgYHtyIHl1Y2F0YW4gaW50ZXJ2ZW50aW9uIDEsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnBvbHkgPC0gc3RfcmVhZChoZXJlKCJJbnRlcnZlbnRpb25zIiwgIk1leF9pbnRlcnZlbnRpb24iLCJtZXhfaW50ZXJ2ZW50aW9uMi5nZW9qc29uIikpCgpwb2xfd2dzIDwtIHN0X3RyYW5zZm9ybShwb2x5LCBjcnM9Y3JzKGJhc2VFU19tW1szXV0pKQpzZXJ2X21leCA8LSBiYXNlRVNfbVtbM11dICU+JSBjcm9wKHBvbF93Z3MpICU+JSBtYXNrKHBvbF93Z3MpCnNlcnZfbWV4IDwtIHByb2plY3Qoc2Vydl9tZXgsIGNycyhwb2x5X3dncyksIG1ldGhvZD0nY3ViaWMnKQpyZXN0X21leCA8LSBjcm9wKHBhX3JjW1szXV0sIHBvbF93Z3MpCnJlc3RfbWV4IDwtIG1hc2socmVzdF9tZXgscG9sX3dncykKd3JpdGVSYXN0ZXIoc2Vydl9tZXgsIGhlcmUoIkludGVydmVudGlvbnMiLCAiTWV4X2ludGVydmVudGlvbiIsICJ5dWNhdGFuX2ludF9yZXN0LnRpZiIpKQp3cml0ZVJhc3RlcihyZXN0X21leCwgaGVyZSgiSW50ZXJ2ZW50aW9ucyIsICJNZXhfaW50ZXJ2ZW50aW9uIiwgIk1leF9ncmlzY29tLnRpZiIpLCBvdmVyd3JpdGU9VFJVRSkKCmBgYAoKIyMjIDMuMy4xIFByZXBhcmUgVGVtcGxhdGUgWXVjYXRhbgpUaGlzIGp1c3QgY3JlYXRlIGEgYmFja2dyb3VuZCBvZiBaZXJvZXMgdG8gdXNlIGFzIHRlbXBsYXRlIGZvciByZXByb2plY3RpbmcgKHRoaXMgaXMgbmVjZXNzYXJ5IGJlY2F1c2UgdGhlIGFjY2VzcyBsYXllciB3aGljIGlzIG9uIGEgZGlmZmVyZW50IGNycy4gTm90IGlkZWFsLCBidXQgbmVlZCB0byBtb3ZlIGZvcndhcmQpCmBgYHtyIGJyYXppbCBpbnRlcnZlbnRpb24sIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnBvbHkgPC0gc3RfcmVhZChoZXJlKCJJbnRlcnZlbnRpb25zIiwgIk1leF9pbnRlcnZlbnRpb24iLCJtZXhfaW50ZXJ2ZW50aW9uMi5nZW9qc29uIikpCnBvbF93Z3MgPC0gc3RfdHJhbnNmb3JtKHBvbHksIGNycz1jcnModG1wW1szXV0pKQpzZXJ2X2JyYSA8LSB0bXBbWzNdXSAlPiUgY3JvcChwb2xfd2dzKSAlPiUgbWFzayhwb2xfd2dzKQpzZXJ2X2JyYSA8LSBwcm9qZWN0KHNlcnZfYnJhLCBjcnMocG9seSksIHJlcz0zMCkKd3JpdGVSYXN0ZXIoc2Vydl9icmEsIGhlcmUoIkludGVydmVudGlvbnMiLCAiTWV4X2ludGVydmVudGlvbiIsICJ5dWNhdGFuX2JrZy50aWYiKSxvdmVyd3JpdGU9VFJVRSkKCmBgYAojIyAzLjMgIFBlcnUKYGBge3IgTWFkcmUgRGUgRGlvcyBpbnRlcnZlbnRpb24sIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnBvbCA8LSBzdF9yZWFkKGhlcmUoIkludGVydmVudGlvbnMiLCJQZXJ1IiwiSW50ZXJ2ZW5jaW9uZXMiLCAiY29tbW9uZGF0YSIsImdhbmFkZXJpYSIsIkdBTkFERVJJQS5zaHAiKSkKcG9sIDwtIHN0X21ha2VfdmFsaWQocG9sKQpzdF93cml0ZShwb2wsIGhlcmUoIkludGVydmVudGlvbnMiLCAiZ2FuYWRlcmlhLnNocCIpKQoKI2dldCBtc2sgbm9uIHplcm8gdmFsdWVzIGZyb20gdGhlIEVDIG1hc2sKbXNrX3AgPC0gY2xhc3NpZnkoYmFzZUVTW1s0XV0scmNsKQpwb2xfd2dzIDwtIHN0X3RyYW5zZm9ybShwb2wsIGNycz1jcnMoYmFzZUVTX21bWzRdXSkpCnNlcnZfcGVyX2dhbiA8LSBiYXNlRVNbWzRdXSAlPiUgY3JvcChwb2xfd2dzKSAlPiUgbWFzayhwb2xfd2dzKQoKcmVzdF9wZXIgPC0gcHJvamVjdChwYV9yY1tbNF1dLCBzZXJ2X3BlcikKcmVzdF9wZXIgPC0gY2xhc3NpZnkocmVzdF9wZXIscmNsKQpzZXJ2X3Blcl9nYW4gPC0gcHJvamVjdChzZXJ2X3Blcl9nYW4sIHNlcnZfcGVyLCBtZXRob2Q9J2JpbGluZWFyJykKbXNrX2cgPC0gY2xhc3NpZnkoc2Vydl9wZXJfZ2FuLHJjbCkgCm1za19nIDwtIHN1YnN0KG1za19nLCBmcm9tPTAsIHRvID0xKQpwZXIxIDwtIHByb2plY3QocGVyMSxzZXJ2X3BlcikKCm1hc2tfYWxsIDwtIG1lcmdlKG1za19nLHJlc3RfcGVyKQptYXNrX2FsbCA8LSBjbGFzc2lmeShtYXNrX2FsbCxyY2wpCm1ha3MgPC0gbGlzdChyZXN0X3BlciwgbXNrX2csIG1hc2tfYWxsKQoKbWFza19hbGxfd2dzIDwtIHByb2plY3QobWFza19hbGwsIGJhc2VFU1tbNF1dKQoKbWtzX3BlcnUgPC0gbWFzayhiYXNlRVNbWzRdXSxtYXNrX2FsbF93Z3MsIG1hc2t2YWx1ZT0wKQoKYXJlYXMgPC0gbGFwcGx5KG1ha3MsbHNtX2NfY2EpCnNhdmUoYXJlYXMsIGZpbGU9aGVyZSgiSW50ZXJ2ZW50aW9ucyIsICJQZXJ1X2ludGVydmVudGlvbiIsIlByb3BvcnRpb25zLlJEYXRhIikpCndyaXRlUmFzdGVyKG1hc2tfYWxsLCBoZXJlKCJJbnRlcnZlbnRpb25zIiwgIlBlcnVfaW50ZXJ2ZW50aW9uIiwiTUREbWFza19maW5hbC50aWYiKSwgb3ZlcndyaXRlPVRSVUUpCndyaXRlUmFzdGVyKG1rc19wZXJ1LCBoZXJlKCJJbnRlcnZlbnRpb25zIiwgIlBlcnVfaW50ZXJ2ZW50aW9uIiwiTURERUVTX2ZpbmFsLnRpZiIpLCBvdmVyd3JpdGU9VFJVRSkKCmBgYAoKIyMgMy40IFZpZXRuYW0KClBlbmRpbmcuLi4KCiMgNCBTYW1wbGluZyBhbmQgRXh0cmFjdGluZyB2YWx1ZXMKClRoaXMgd2lsbCBiZSBkZWFsdCBvbiBhIHR3byBwYXJ0IGJhc2lzOgoxLklkZW50aWZ5IHRoZSBoZWN0YXJlcyB0aGF0IHlpZWxkIHRoZSBtYXhpbXVtIGFnZ3JlZ2F0ZWQgcmVzdG9yYXRpb24gdmFsdWVzIHdpdGhpbmcgdGhlIEdyaXNjb20gcmVzdG9yYXRpb24gcG90ZW50aWFsIHBpeGVscy4gQ29udGluZ2VudCBvbiB0aGUgZW50cnkgYXNzdW1wdGlvbnMKMi4gTW9kZWwgdGhlIGVzdGltYXRlZCB2YWx1ZXMgb2YgRVMgZ2FpbnMgZm9yIHRoZSBzZXJ2aWNlcyBiYXNlZCBvbiBhIHJhbmRvbSBzYW1wbGluZy4KVGhpcyBzZWNvbmQgcGFydCBoYXMgaW1wbGljaXQgYSBjb3VwbGUgb2YgYXNzdW1wdGlvbnM6IAoKLSBXZSBhcmUgbm90IGNvbnNpZGVyaW5nIGFueSBzcGF0aWFsIGNvbmZpZ3VyYXRpb24gKGxhbmRzY2FwZSBtZXRyaWNzKSBhc3BlY3RzIGFmZmVjdGluZyB0aGUgdG90YWwgdmFsdWUKLSBFdmVudHVhbGx5LCB0aGUgbW9kZWwgY2FuIGJlIHJlZmluZWQgYnkgaW5jb3Jwb3JhdGluZyBhZGRpdGlvbmFsIHBhcmFtZXRlcnMgKGUuZyBtaW5pbXVtIGRpc3RhbmNlIHRvIGJvdW5kYXJpZXMsIGRpc3RhbmNlIGJldHdlZW4gcG9pbnRzLCB0b3BvZ3JhcGh5IG9yIGluaGFiaXRlZCBhcmVhcyAoc29tZSBvZiBpdCBpcyBpbXBsaWNpdCBpbiB0aGUgaW5wdXQgZGF0YSwgYnV0IG5lZWRzIHRvIGJlIGNvbmZpcm1lZCkuCi0gQ29hc3RhbCByaXNrIHByb3RlY3Rpb24gb25seSBvY2N1cnMgYXQgdGhlIGNvYXN0LCBhbnkgcmFuZG9tIHNhbXBsaW5nIHBlcmZvcm1lZCB3aWxsIGhhdmV0byBjb25zaWRlciB0aGlzLiBUaGlzIGNhbiBiZSBhZGp1c3RlZCB1c2luZyB3ZWlnaHRzLgoKClRoaXMgYXBwcm9hY2ggdXRpbGl6ZXMgYSBzdHJhdGlmaWVkIHJhbmRvbSBzYW1wbGluZyB0ZWNobmlxdWUgdG8gZXN0aW1hdGUgdGhlIG1lYW4gdmFsdWVzIG9mIGRpZmZlcmVudCBiYW5kcyBpbiBhIG11bHRpLWJhbmQgcmFzdGVyIGRhdGFzZXQuIFN0cmF0aWZpZWQgcmFuZG9tIHNhbXBsaW5nIGlzIGEgcHJvYmFiaWxpdHkgc2FtcGxpbmcgbWV0aG9kIHdoZXJlIHRoZSBwb3B1bGF0aW9uIGlzIGRpdmlkZWQgaW50byBob21vZ2VuZW91cyBzdWJncm91cHMgY2FsbGVkIHN0cmF0YSwgYW5kIHJhbmRvbSBzYW1wbGVzIGFyZSB0YWtlbiBmcm9tIGVhY2ggc3RyYXR1bS4gSW4gdGhpcyBjYXNlLCB0aGUgc3RyYXRhIGFyZSBkZWZpbmVkIGJ5IHRoZSBzcGF0aWFsIGV4dGVudCBvZiB0aGUgcmFzdGVyIGRhdGFzZXQsIGFuZCB0aGUgcGl4ZWxzIHdpdGhpbiB0aGUgcmFzdGVyIHJlcHJlc2VudCB0aGUgaW5kaXZpZHVhbCBzYW1wbGluZyB1bml0cy4KCk1ldGhvZG9sb2d5CgpEZWZpbmUgdGhlIEFyZWEgb2YgSW50ZXJlc3Q6IFRoZSBmaXJzdCBzdGVwIGlzIHRvIGRlZmluZSB0aGUgYXJlYSBvZiBpbnRlcmVzdCAoQU9JKSB3aXRoaW4gdGhlIHJhc3RlciBkYXRhc2V0LiBUaGlzIEFPSSByZXByZXNlbnRzIHRoZSBzcGF0aWFsIGV4dGVudCBmcm9tIHdoaWNoIHRoZSBzYW1wbGVzIHdpbGwgYmUgZHJhd24uIEluIHRoaXMgc3BlY2lmaWMgY2FzZSwgdGhlIEFPSSBpcyBkZWZpbmVkIGFzIDMwLDAwMCBoZWN0YXJlcy4KCkNhbGN1bGF0ZSB0aGUgU2FtcGxlIFNpemU6IEJhc2VkIG9uIHRoZSByZXNvbHV0aW9uIG9mIHRoZSByYXN0ZXIgYW5kIHRoZSBkZXNpcmVkIEFPSSwgdGhlIHJlcXVpcmVkIG51bWJlciBvZiBwaXhlbHMgdG8gYmUgc2FtcGxlZCBpcyBjYWxjdWxhdGVkLiBUaGlzIGVuc3VyZXMgdGhhdCB0aGUgdG90YWwgYXJlYSBjb3ZlcmVkIGJ5IHRoZSBzYW1wbGVkIHBpeGVscyBjb3JyZXNwb25kcyB0byB0aGUgZGVmaW5lZCBBT0kuCgpQZXJmb3JtIFN0cmF0aWZpZWQgUmFuZG9tIFNhbXBsaW5nOiBUaGUgc3BhdFNhbXBsZSgpIGZ1bmN0aW9uIGZyb20gdGhlIHRlcnJhIHBhY2thZ2UgaW4gUiBpcyB1c2VkIHRvIHBlcmZvcm0gc3RyYXRpZmllZCByYW5kb20gc2FtcGxpbmcuIFRoaXMgZnVuY3Rpb24gYWxsb3dzIGZvciByYW5kb20gc2FtcGxpbmcgb2YgcGl4ZWxzIHdpdGhpbiB0aGUgZGVmaW5lZCBBT0ksIHdoaWxlIGFsc28gZXhjbHVkaW5nIHBpeGVscyB3aXRoICJOQSIgdmFsdWVzIGluIGFsbCBiYW5kcywgZW5zdXJpbmcgdGhhdCBvbmx5IHZhbGlkIGRhdGEgcG9pbnRzIGFyZSBpbmNsdWRlZCBpbiB0aGUgYW5hbHlzaXMuCgpSZXBlYXQgU2FtcGxpbmc6IFRvIHJlZHVjZSBwb3RlbnRpYWwgc2FtcGxpbmcgYmlhcyBhbmQgaW1wcm92ZSB0aGUgYWNjdXJhY3kgb2YgdGhlIGVzdGltYXRlcywgdGhlIHJhbmRvbSBzYW1wbGluZyBwcm9jZXNzIGlzIHJlcGVhdGVkIG11bHRpcGxlIHRpbWVzIChpbiB0aGlzIGNhc2UsIDMwIHRpbWVzKS4gVGhpcyBpcyBhbmFsb2dvdXMgdG8gdGhlIGNvbmNlcHQgb2YgYm9vdHN0cmFwcGluZywgd2hlcmUgcmVwZWF0ZWQgc2FtcGxpbmcgd2l0aCByZXBsYWNlbWVudCBpcyB1c2VkIHRvIGVzdGltYXRlIHRoZSBzYW1wbGluZyBkaXN0cmlidXRpb24gb2YgYSBzdGF0aXN0aWMuCgpDYWxjdWxhdGUgU3VtbWFyeSBTdGF0aXN0aWNzOiBGb3IgZWFjaCByZXBldGl0aW9uLCB0aGUgbWVhbiwgc3RhbmRhcmQgZGV2aWF0aW9uLCBhbmQgOTUlIGNvbmZpZGVuY2UgaW50ZXJ2YWxzIGFyZSBjYWxjdWxhdGVkIGZvciBlYWNoIGJhbmQgaW4gdGhlIHJhc3RlciBkYXRhc2V0LiBUaGlzIHByb3ZpZGVzIGEgbWVhc3VyZSBvZiB0aGUgY2VudHJhbCB0ZW5kZW5jeSBhbmQgdmFyaWFiaWxpdHkgb2YgdGhlIHNhbXBsZWQgZGF0YS4KClN5bnRoZXNpemUgUmVzdWx0czogVGhlIHJlc3VsdHMgZnJvbSBhbGwgcmVwZXRpdGlvbnMgYXJlIGNvbWJpbmVkIHRvIGNhbGN1bGF0ZSBhbiBvdmVyYWxsIG1lYW4gYW5kIGNvbmZpZGVuY2UgaW50ZXJ2YWwgZm9yIGVhY2ggYmFuZC4gVGhpcyBwcm92aWRlcyBhIG1vcmUgcm9idXN0IGVzdGltYXRlIG9mIHRoZSBleHBlY3RlZCB2YWx1ZXMsIGVmZmVjdGl2ZWx5IGNvcnJlY3RpbmcgZm9yIHBvdGVudGlhbCBvdXRsaWVycyBhbmQgcmVkdWNpbmcgdGhlIGluZmx1ZW5jZSBvZiBpbmRpdmlkdWFsIHNhbXBsZSB2YXJpYXRpb25zLgoKVGhlb3JldGljYWwgSnVzdGlmaWNhdGlvbgoKVGhlIHVzZSBvZiBzdHJhdGlmaWVkIHJhbmRvbSBzYW1wbGluZyBpcyBqdXN0aWZpZWQgYXMgaXQgZW5zdXJlcyB0aGF0IHRoZSBzYW1wbGUgaXMgcmVwcmVzZW50YXRpdmUgb2YgdGhlIGVudGlyZSBwb3B1bGF0aW9uIChpLmUuLCBhbGwgcGl4ZWxzIHdpdGhpbiB0aGUgQU9JKS4gQnkgZGl2aWRpbmcgdGhlIHBvcHVsYXRpb24gaW50byBzdHJhdGEgYW5kIHNhbXBsaW5nIGZyb20gZWFjaCBzdHJhdHVtLCB0aGlzIG1ldGhvZCByZWR1Y2VzIHRoZSB2YXJpYWJpbGl0eSBvZiB0aGUgZXN0aW1hdGVzIGNvbXBhcmVkIHRvIHNpbXBsZSByYW5kb20gc2FtcGxpbmcuIFRoaXMgaXMgcGFydGljdWxhcmx5IGltcG9ydGFudCB3aGVuIGRlYWxpbmcgd2l0aCBzcGF0aWFsIGRhdGEsIHdoZXJlIHRoZXJlIG1heSBiZSBpbmhlcmVudCBzcGF0aWFsIGF1dG9jb3JyZWxhdGlvbiBvciBoZXRlcm9nZW5laXR5LgoKVGhlIHJlcGVhdGVkIHNhbXBsaW5nIGFwcHJvYWNoIGZ1cnRoZXIgZW5oYW5jZXMgdGhlIHJvYnVzdG5lc3Mgb2YgdGhlIGVzdGltYXRlcyBieSBwcm92aWRpbmcgYSBkaXN0cmlidXRpb24gb2YgcG9zc2libGUgdmFsdWVzLiBUaGlzIGFsbG93cyBmb3IgdGhlIGNhbGN1bGF0aW9uIG9mIGNvbmZpZGVuY2UgaW50ZXJ2YWxzLCB3aGljaCBwcm92aWRlIGEgbWVhc3VyZSBvZiB0aGUgdW5jZXJ0YWludHkgYXNzb2NpYXRlZCB3aXRoIHRoZSBlc3RpbWF0ZXMuIEJ5IHN5bnRoZXNpemluZyB0aGUgcmVzdWx0cyBmcm9tIG11bHRpcGxlIHJlcGV0aXRpb25zLCB0aGUgb3ZlcmFsbCBlc3RpbWF0ZXMgYXJlIGxlc3Mgc3VzY2VwdGlibGUgdG8gdGhlIGluZmx1ZW5jZSBvZiBpbmRpdmlkdWFsIHNhbXBsZSB2YXJpYXRpb25zIGFuZCBwcm92aWRlIGEgbW9yZSBhY2N1cmF0ZSByZXByZXNlbnRhdGlvbiBvZiB0aGUgdHJ1ZSBwb3B1bGF0aW9uIHZhbHVlcy4KClJlZmVyZW5jZXMKCkNvY2hyYW4sIFcuIEcuICgxOTc3KS4gU2FtcGxpbmcgdGVjaG5pcXVlcyAoM3JkIGVkLikuIEpvaG4gV2lsZXkgJiBTb25zLgpMb2hyLCBTLiBMLiAoMjAxMCkuIFNhbXBsaW5nOiBEZXNpZ24gYW5kIGFuYWx5c2lzICgybmQgZWQuKS4gQnJvb2tzL0NvbGUuIDEgIAoxLgpCaXZhbmQsIFIuIFMuLCBQZWJlc21hLCBFLiBKLiwgJiBHw7NtZXotUnViaW8sIFYuICgyMDEzKS4gQXBwbGllZCBzcGF0aWFsIGRhdGEgYW5hbHlzaXMgd2l0aCBSICgybmQgZWQuKS4gU3ByaW5nZXIuCgoKIyMgNC4xIEVzcGlyaXRvIFNhbnRvCgojIyMgNC4xLjEgUHJlcGFyZSBEYXRhIEVzcCBTYW50by4KCkFsaWduIGFuZCByZXNhbXBlIGFsbCB0aGUgcmFzdGVyIGRhdGFzZXRzIHRvIHRoZSBzYW1lIGNycyBhbmQgb3JpZ2luLgoKYGBge3IgZmlsdGVyIGRhdGEgMSwgZXZhbD1GQUxTRSwgaW5jbHVkZT1GQUxTRX0Kc2VydiA8LSByYXN0KGhlcmUoIkludGVydmVudGlvbnMiLCAiQnJhemlsX2ludGVydmVudGlvbiIsICJlc3Bfc2FudG9fYmtnLnRpZiIpKQphX2ZpbGVzIDwtIHRpZmZlc1tncmVwKCJCUkFaSUwiLCB0aWZmZXMpXQojYV9maWxlcyA8LSBhX2ZpbGVzWzJdCnNlcnZfMSA8LSBsYXBwbHkoYV9maWxlcywgcmFzdCkKdGYgPC0gYmFzZW5hbWUoYV9maWxlcykKdGVtcCA8LSB0cmltKHByb2plY3Qoc2Vydiwgc2Vydl8xW1sxXV0pKQpzZXJ2XzEgPC0gbGFwcGx5KHNlcnZfMSwgZnVuY3Rpb24ocil7CiAgciA8LSBjcm9wKHIsdGVtcCwgc25hcD0gImluIiwgZXh0ZW5kPVRSVUUpCiAgaWYgKCFjb21wYXJlR2VvbShyLCB0ZW1wLCBzdG9wT25FcnJvciA9IEZBTFNFKSkgewogICAgICBtZXNzYWdlKCJBbGlnbmluZyByYXN0ZXI6ICIsIG5hbWVzKHIpKQogICAgICAjIFJlc2FtcGxlIHRvIGFsaWduIHdpdGggdGhlIHRlbXBsYXRlCiAgICAgIHJlc2FtcGxlKHIsIHRlbXAsIG1ldGhvZCA9ICJiaWxpbmVhciIpCiAgICB9IGVsc2UgewogICAgICAjIFJldHVybiByYXN0ZXIgYXMgaXMgaWYgYWxyZWFkeSBhbGlnbmVkCiAgICAgIG1lc3NhZ2UoIlJhc3RlciBhbHJlYWR5IGFsaWduZWQ6ICIsIG5hbWVzKHIpKQogICAgICByCiAgICB9CiAgciA8LSB0cmltKHIpCiAgI3IgPC0gbWFzayhyLHRlbXApCnIgPC0gcHJvamVjdChyLCBzZXJ2LCBtZXRob2QgPSAnYmlsaW5lYXInKQp9KQoKc2Vydl8xIDwtIGxhcHBseShzZXJ2XzEsIGZ1bmN0aW9uKHIpewogIHIgPC0gbWFzayhyLHNlcnYpCn0pCgptYXAoMTpsZW5ndGgoc2Vydl8xKSwgZnVuY3Rpb24oeCkgd3JpdGVSYXN0ZXIoc2Vydl8xW1t4XV0sIHBhc3RlMChoZXJlKCJJbnRlcnZlbnRpb25zIiwgIkJyYXppbF9pbnRlcnZlbnRpb24iKSwgJy8nLCB0Zlt4XSksIG92ZXJ3cml0ZT1UUlVFKSkKc2Vydl8xIDwtIGxhcHBseSh0aWZmZXMsIHJhc3QpCnNlcnZfMSA8LSAoZG8uY2FsbChjLHNlcnZfMSkpCnNlcnZfMSA8LSB0cmltKG1lcmdlKHNlcnZfMSxzZXJ2KSkgI2FkZCBiYWNrZ3JvdW5kIG9mIFplcm9zCndyaXRlUmFzdGVyKHNlcnZfMSwgcGFzdGUwKGhlcmUoIkludGVydmVudGlvbnMiLCAiQnJhemlsX2ludGVydmVudGlvbiIpLCcvJywgJ3NlcnZfQlJBWklMLnRpZicpLCBvdmVyd3JpdGU9VFJVRSkKYGBgCgoKIyMjIDQuMS4yIFJ1biBTYW1wbGluZyBhbmQgU3ludGV0aXplIHJlc3VsdHMgLSBFc3Bpcml0byBTYW50bwoKSGVyZSwgd2UgYXJlIHNhbXBsaW5nIHRoZSBkYXRhIGZvciBvYnRhaW4gZXN0aW1hdGUgb2YgdGhlIGV4cGVjdGVkIHJlc3RvcmF0aW9uIGdhaW5zIGFzc3VtaW5nIHJhbmRvbWx5IHNlbGVjdGVkIHBpeGVscyBleHRyYWN0ZWQgZm9ybSB0aGUgcG90ZW50aWFsIHJlc3RvcmF0aW9uIGFyZWFzLiBBZ2Fpbiwgc29tZSBhc3N1bXB0aW9ucyB3aWxsIGhhdmUgdG8gYmUgcmV2aWV3ZWQsIGJ1dCB0aGlzIGlzIGFuIGluaXRpYWwgYXNzZXNzbWVudC4KVGhlIHRhcmdldGVkIGludGVydmVudGlvbiBhcmVhIGlzIDMwLjIwMCBoYS4KCmBgYHtyIHNhbXBsaW5nIHRhcmdldCBhcmVhcyBicmF6aWwsIGV2YWw9RkFMU0UsIGluY2x1ZGU9RkFMU0V9CnNlcnZfMSA8LSByYXN0KGhlcmUoIkludGVydmVudGlvbnMiLCAiQnJhemlsX2ludGVydmVudGlvbiIsJy8nLCAnc2Vydl9CUkFaSUwudGlmJykpCnJlc3RfbSA8LSByYXN0KGhlcmUoJ0ludGVydmVudGlvbnMnLCAnQnJhemlsX2ludGVydmVudGlvbicsICdTU19ncmlzY29tLnRpZicpKQpyY2wgPC0gbWF0cml4KGMoCiAgLUluZiwgMCwgMCwgICMgQW55IHZhbHVlIGZyb20gLUluZmluaXR5IHRvIDAgcmVtYWlucyAwCiAgMCwgSW5mLCAxICAgIyBBbnkgdmFsdWUgZnJvbSAwIHRvIEluZmluaXR5IGJlY29tZXMgMQopLCBuY29sID0gMywgYnlyb3cgPSBUUlVFKQpyZXN0X20gPC0gY2xhc3NpZnkocmVzdF9tLCByY2wpCgpyZXN0X20gPC1wcm9qZWN0KHJlc3RfbSwgc2Vydl8xKQpyZXN0X20gPC0gdGVycmE6OnJlc2FtcGxlKHJlc3RfbSwgc2Vydl8xKQpzZXJ2XzEgPC0gbWFzayhzZXJ2XzEscmVzdF9tLCBtYXNrdmFsdWVzPTApCiNDYWxjdWxhdGUgdGhlIG51bWJlciBvZiBwaXhlbHMgbmVlZGVkIGZvciAzMCwwMDAgaGVjdGFyZXMKcGl4ZWxfYXJlYSA8LSAzMCAqIDMwICAjIEFyZWEgb2YgYSBzaW5nbGUgcGl4ZWwgaW4gc3F1YXJlIG1ldGVycyAoMzBtIHJlc29sdXRpb24pCmhlY3RhcmVfYXJlYSA8LSAxMDAwMCAgIyBBcmVhIG9mIG9uZSBoZWN0YXJlIGluIHNxdWFyZSBtZXRlcnMKcGl4ZWxzX25lZWRlZCA8LSByb3VuZCgoMzAyMDAgKiBoZWN0YXJlX2FyZWEpIC8gcGl4ZWxfYXJlYSkKCiMgTnVtYmVyIG9mIHJlcGV0aXRpb25zCm5fcmVwZXRpdGlvbnMgPC0gMzAKIyBGdW5jdGlvbiB0byBwZXJmb3JtIHRoZSBzYW1wbGluZyBhbmQgY2FsY3VsYXRpb25zCnNhbXBsZV9hbmRfY2FsY3VsYXRlIDwtIGZ1bmN0aW9uKGksIHJhc3RlciwgcGl4ZWxzX25lZWRlZCkgewogICMgU2FtcGxlIHBpeGVscyBhbmQgZGlyZWN0bHkgZXh0cmFjdCB2YWx1ZXMgKHdpdGhvdXQgbmEucm0pCiAgc2FtcGxlX3ZhbHVlcyA8LSBzcGF0U2FtcGxlKHJhc3Rlciwgc2l6ZSA9IHBpeGVsc19uZWVkZWQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAicmFuZG9tIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hLnJtID0gRkFMU0UsICAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXMucG9pbnRzID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4eSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBUUlVFKSAKCiAgIyBSZW1vdmUgcm93cyB3aGVyZSBBTEwgdmFsdWVzIGFyZSBOQQogIHNhbXBsZV92YWx1ZXMgPC0gc2FtcGxlX3ZhbHVlc1tyb3dTdW1zKGlzLm5hKHNhbXBsZV92YWx1ZXMpKSAhPSBuY29sKHNhbXBsZV92YWx1ZXMpLCBdCgogICMgSWYgbm90IGVub3VnaCBzYW1wbGVzIGFmdGVyIHJlbW92aW5nIE5BcywgcmVzYW1wbGUKICBpZiAobnJvdyhzYW1wbGVfdmFsdWVzKSA8IHBpeGVsc19uZWVkZWQpIHsKICAgIHNhbXBsZV92YWx1ZXMgPC0gcmJpbmQoCiAgICAgIHNhbXBsZV92YWx1ZXMsCiAgICAgIHNwYXRTYW1wbGUocmFzdGVyLCBzaXplID0gcGl4ZWxzX25lZWRlZCAtIG5yb3coc2FtcGxlX3ZhbHVlcyksCiAgICAgICAgICAgICAgICAgbWV0aG9kID0gInJhbmRvbSIsIG5hLnJtID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgYXMucG9pbnRzID0gRkFMU0UsIHh5ID0gRkFMU0UsIHZhbHVlcyA9IFRSVUUpCiAgICApCiAgfQoKICAjIENhbGN1bGF0ZSBzdW1tYXJ5IHN0YXRpc3RpY3MKICBiYW5kX3N0YXRzIDwtIGFwcGx5KHNhbXBsZV92YWx1ZXMsIDIsIGZ1bmN0aW9uKHgpIHsgCiAgICBtZWFuX3ZhbCA8LSBtZWFuKHgpCiAgICBzZF92YWwgPC0gc2QoeCkKICAgIG5fdmFsIDwtIGxlbmd0aCh4KQogICAgc2VfdmFsIDwtIHNkX3ZhbCAvIHNxcnQobl92YWwpCiAgICBtYXJnaW5fZXJyb3IgPC0gcXQoMC45NzUsIGRmID0gbl92YWwgLSAxKSAqIHNlX3ZhbAogICAgbG93ZXJfY2kgPC0gbWVhbl92YWwgLSBtYXJnaW5fZXJyb3IKICAgIHVwcGVyX2NpIDwtIG1lYW5fdmFsICsgbWFyZ2luX2Vycm9yCiAgICByZXR1cm4oYyhtZWFuID0gbWVhbl92YWwsIGxvd2VyX2NpID0gbG93ZXJfY2ksIHVwcGVyX2NpID0gdXBwZXJfY2kpKQogIH0pCgogIGJhbmRfc3RhdHNfZGYgPC0gYXMuZGF0YS5mcmFtZSh0KGJhbmRfc3RhdHMpKQogIGJhbmRfc3RhdHNfZGYkcmVwZXRpdGlvbiA8LSBpCgogICMgQ2FsY3VsYXRlIHN1bSBvZiBwaXhlbCB2YWx1ZXMgZm9yIGVhY2ggYmFuZAogIGJhbmRfc3VtcyA8LSBjb2xTdW1zKHNhbXBsZV92YWx1ZXMpIAogIGJhbmRfc3RhdHNfZGYkc3VtIDwtIGJhbmRfc3VtcwoKICByZXR1cm4oYmFuZF9zdGF0c19kZikKfQoKIyBVc2luZyBtY2xhcHBseSAocGFyYWxsZWwgcHJvY2Vzc2luZykKbnVtX2NvcmVzIDwtIDE1IApyZXN1bHRzX2xpc3QgPC0gbWNsYXBwbHkoMTpuX3JlcGV0aXRpb25zLCBzYW1wbGVfYW5kX2NhbGN1bGF0ZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICByYXN0ZXIgPSBzZXJ2XzEsIAogICAgICAgICAgICAgICAgICAgICAgICAgcGl4ZWxzX25lZWRlZCA9IHBpeGVsc19uZWVkZWQsCiAgICAgICAgICAgICAgICAgICAgICAgICBtYy5jb3JlcyA9IG51bV9jb3JlcykgCgpyZXN1bHRzX2xpc3QgPC0gbGFwcGx5KHJlc3VsdHNfbGlzdCwgZnVuY3Rpb24oZGYpewogIGRmIDwtIGRmICU+JSBtdXRhdGUoYmFuZD1yb3duYW1lcyhkZikpCn0pCiMgQ29tYmluZSBhbGwgcmVzdWx0cyBpbnRvIGEgc2luZ2xlIGRhdGEgZnJhbWUKYWxsX3Jlc3VsdHMgPC0gYXNfdGliYmxlKGRvLmNhbGwocmJpbmQsIHJlc3VsdHNfbGlzdCkpCgoKIyBBZGQgbmV3IGNvbHVtbnMgd2l0aCB0aGUgc2VydmljZSBuYW1lcyBhbmQgdW5pdHMuCmFsbF9yZXN1bHRzIDwtIGFsbF9yZXN1bHRzICU+JQogIG11dGF0ZShTZXJ2aWNlID0gY2FzZV93aGVuKAogICAgYmFuZCA9PSAiY3ZfaGFiaXRhdF92YWx1ZV9TYzN2MS1FU0Ftb2QyX3YyX21kNV82NDA4MmIiIH4gIkNvYXN0YWwgUHJvdGVjdGlvbiIsCiAgICBiYW5kID09ICJuYXR1cmVfYWNjZXNzX2RpZmZfU2MzdjFfUE5Wbm9hZy1lc2EyMDIwIiB+ICJOYXR1cmUgQWNjZXNzIiwKICAgIGJhbmQgPT0gIm5pdHJvZ2VuX0VTQW1vZDItU2MzdjFfbWQ1XzAyNGEzNiIgfiAiTml0cm9nZW4gRXhwb3J0IiwKICAgIGJhbmQgPT0gInBvbGxpbmF0aW9uX3BwbF9mZWRfb25fYWdfMTBzX1NjM3YxX1BOVm5vYWctZXNhMjAyMF9tZDVfNDA1Yzg4IiB+ICJQb2xsaW5hdGlvbiIsCiAgICBiYW5kID09ICJwb2xsaW5hdGlvbl9wcGxfZmVkX29uX2hhYl9TYzN2MV9QTlZfbm9fYWctRVNBX21kNV81NzY3OTAiIH4gIlBvbGxpbmF0aW9uIChwZW9wbGUgZmVkIG9uIEhhYikiLAogICAgYmFuZCA9PSAic2VkaW1lbnRfRVNBbW9kMi1TYzN2MV9tZDVfMTQ5MDc4IiB+ICJTZWRpbWVudCBFeHBvcnQiLAogICAgIyAuLi4gYWRkIG1vcmUgY2FzZXMgZm9yIG90aGVyIGJhbmRzIC4uLgogICAgVFJVRSB+IGJhbmQgICMgS2VlcCB0aGUgb3JpZ2luYWwgYmFuZCBuYW1lIGlmIG5vIG1hdGNoCiAgKSkKCmFsbF9yZXN1bHRzIDwtIGFsbF9yZXN1bHRzICU+JQogIG11dGF0ZSh1bml0cyA9IGNhc2Vfd2hlbigKICAgIGJhbmQgPT0gImN2X2hhYml0YXRfdmFsdWVfU2MzdjEtRVNBbW9kMl92Ml9tZDVfNjQwODJiIiB+ICJSaXNrIFJlZHVjdGlvbiBJbmRleCIsCiAgICBiYW5kID09ICJuYXR1cmVfYWNjZXNzX2RpZmZfU2MzdjFfUE5Wbm9hZy1lc2EyMDIwIiB+ICJQZW9wbGUgd2l0aGluIDEgaG91ciIsCiAgICBiYW5kID09ICJuaXRyb2dlbl9FU0Ftb2QyLVNjM3YxX21kNV8wMjRhMzYiIH4gIk5pdHJvZ2VuIEV4cG9ydCAoa2cvaGEveWVhcikiLAogICAgYmFuZCA9PSAicG9sbGluYXRpb25fcHBsX2ZlZF9vbl9hZ18xMHNfU2MzdjFfUE5Wbm9hZy1lc2EyMDIwX21kNV80MDVjODgiIH4gIlBvbGxpbmF0aW9uIChlcXVpdmFsZW50IHBlb3BsZSBmZWQpIiwKICAgIGJhbmQgPT0gInBvbGxpbmF0aW9uX3BwbF9mZWRfb25faGFiX1NjM3YxX1BOVl9ub19hZy1FU0FfbWQ1XzU3Njc5MCIgfiAiUG9sbGluYXRpb24gKHBlb3BsZSBmZWQgb24gaGFiKSIsCiAgICBiYW5kID09ICJzZWRpbWVudF9FU0Ftb2QyLVNjM3YxX21kNV8xNDkwNzgiIH4gIlNlZGltZW50IEV4cG9ydCAodG9uL2tnL3llYXIpIiwKICAgICMgLi4uIGFkZCBtb3JlIGNhc2VzIGZvciBvdGhlciBiYW5kcyAuLi4KICAgIFRSVUUgfiBiYW5kICAjIEtlZXAgdGhlIG9yaWdpbmFsIGJhbmQgbmFtZSBpZiBubyBtYXRjaAogICkpCgphbGxfcmVzdWx0cyA8LSBhbGxfcmVzdWx0cyAlPiUKICBtdXRhdGUoY29sb3IgPSBjYXNlX3doZW4oCiAgICBiYW5kID09ICJjdl9oYWJpdGF0X3ZhbHVlX1NjM3YxLUVTQW1vZDJfdjJfbWQ1XzY0MDgyYiIgfiAiIzdhMDE3NyIsCiAgICBiYW5kID09ICJuYXR1cmVfYWNjZXNzX2RpZmZfU2MzdjFfUE5Wbm9hZy1lc2EyMDIwIiB+ICIjQTU3QzAwIiwKICAgIGJhbmQgPT0gIm5pdHJvZ2VuX0VTQW1vZDItU2MzdjFfbWQ1XzAyNGEzNiIgfiAiIzJjOTQ0YyIsCiAgICBiYW5kID09ICJwb2xsaW5hdGlvbl9wcGxfZmVkX29uX2FnXzEwc19TYzN2MV9QTlZub2FnLWVzYTIwMjBfbWQ1XzQwNWM4OCIgfiAiI2RkMWM3NyIsCiAgICBiYW5kID09ICJwb2xsaW5hdGlvbl9wcGxfZmVkX29uX2hhYl9TYzN2MV9QTlZfbm9fYWctRVNBX21kNV81NzY3OTAiIH4gIiNkZDFiNTYiLAogICAgYmFuZCA9PSAic2VkaW1lbnRfRVNBbW9kMi1TYzN2MV9tZDVfMTQ5MDc4IiB+ICIjMDgzMDZiIiwKICAgICMgLi4uIGFkZCBtb3JlIGNhc2VzIGZvciBvdGhlciBiYW5kcyAuLi4KICAgIFRSVUUgfiBiYW5kICAjIEtlZXAgdGhlIG9yaWdpbmFsIGJhbmQgbmFtZSBpZiBubyBtYXRjaAogICkpCnNhdmUoYWxsX3Jlc3VsdHMsIGZpbGU9IGhlcmUoIkludGVydmVudGlvbnMiLCAiQnJhemlsX2ludGVydmVudGlvbiIsICJhbGxfcmVzX2JyYS5SRGF0YSIpKQpgYGAKIAogCiMjIyA0LjEuMyBQbG90IFJlc3VsdHMgRXNwaXJpdG8gU2FudG8KCmBgYHtyIHBsb3QgYnJhemlsIG91dHB1cywgZWNobz1GQUxTRX0KbG9hZChoZXJlKCJJbnRlcnZlbnRpb25zIiwgIkJyYXppbF9pbnRlcnZlbnRpb24iLCAiYWxsX3Jlc19icmEuUkRhdGEiKSkKZGYgPC1hbGxfcmVzdWx0cyAlPiUgIGZpbHRlcihiYW5kIT0ibmF0dXJlX2FjY2Vzc19kaWZmX1NjM3YxX1BOVm5vYWctZXNhMjAyMCIpICU+JSBmaWx0ZXIoYmFuZCE9ICJwb2xsaW5hdGlvbl9wcGxfZmVkX29uX2hhYl9TYzN2MV9QTlZfbm9fYWctRVNBX21kNV81NzY3OTAiKQojIEFzc3VtaW5nIHlvdXIgJ2FsbF9yZXN1bHRzJyBkYXRhIGZyYW1lIGhhcyB0aGUgY29sdW1ucyAnU2VydmljZScsICd1bml0cycsIGFuZCAnY29sb3InCiMgQXNzdW1pbmcgeW91ciAnYWxsX3Jlc3VsdHMnIGRhdGEgZnJhbWUgaGFzIHRoZSBjb2x1bW5zICdTZXJ2aWNlJywgJ3VuaXRzJywgYW5kICdjb2xvcicKCiMgR2VuZXJhdGUgdGhlIGdncGxvdCBvYmplY3QKcGxvdCA8LSBnZ3Bsb3QoZGYsIGFlcyh5ID0gc3VtLCBmaWxsID0gY29sb3IpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIGxhYnModGl0bGUgPSBzdHJfd3JhcCgiVG90YWwgZXN0aW1hdGVkIHNlcnZpY2UgY2hhbmdlIGluIHVuaXRzIGZvciB0aGUgdGFyZ2V0IGludGVydmVudGlvbiBhcmVhIC0gRXNwaXJpdG8gU2FudG8iLCB3aWR0aCA9IDUwKSwgCiAgICAgICB5ID0gIlRvdGFsIFN1bSBWYWx1ZSIpICsKICB0aGVtZV9idygpICsKICB0aGVtZSgKICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLAogICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoZmFjZSA9ICJib2xkIiksCiAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIgICMgUmVtb3ZlIGxlZ2VuZCBzaW5jZSBjb2xvciBpcyBhbHJlYWR5IG1hcHBlZAogICkgKwogIHNjYWxlX2ZpbGxfaWRlbnRpdHkoKSArIAogIGZhY2V0X3dyYXAofiBTZXJ2aWNlLCBzY2FsZXMgPSAiZnJlZV95IiwgbGFiZWxsZXIgPSBsYWJlbGxlcihTZXJ2aWNlID0gbGFiZWxfd3JhcF9nZW4od2lkdGggPSAxMCkpKSArICAKICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gZnVuY3Rpb24oeCkgewogICAgaWYgKG1heCh4LCBuYS5ybSA9IFRSVUUpID4gMTAwMDAwKSB7CiAgICAgIHBhc3RlMChmb3JtYXQoeCAvIDEwMDAsIGJpZy5tYXJrID0gIi4iLCBkZWNpbWFsLm1hcmsgPSAiLCIpLCAiayIpCiAgICB9IGVsc2UgewogICAgICBmb3JtYXQoeCwgYmlnLm1hcmsgPSAiLiIsIGRlY2ltYWwubWFyayA9ICIsIikKICAgIH0KICB9KSAKcGxvdApgYGAKCiMjIDQuMiBZdWNhdGFuCgpUaGUgYXBwcm9hY2ggaXMgdGhlIHNhbWUgYXMgaW4gQnJhemlsLgpUd28gbWFpbiBpbnRlcnZlbnRpb24gYXJlYXMgd2VyZSB1c2VkIHRybyBidWlsZCB0aGUgZmluYWwgcG9seWdvbjogdGhlIGphZ3VhciBjb3JyaWRvciBhbmQgCiMjIyA0LjIuMSBQcmVwYXJlIERhdGEgWXVjYXRhbi4KQWxpZ24gYW5kIHJlc2FtcGxlIGFsbCB0aGUgcmFzdGVyIGJhbmRzIHRvIHRoZSBhbWUgY3JzIGFuZCBvcmlnaW4uCgpgYGB7ciBmaWx0ZXIgZGF0YSAyLCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQpzZXJ2IDwtIHJhc3QoaGVyZSgiSW50ZXJ2ZW50aW9ucyIsICJNZXhfaW50ZXJ2ZW50aW9uIiwgInl1Y2F0YW5fYmtnLnRpZiIpKQphX2ZpbGVzIDwtIHRpZmZlc1tncmVwKCJNRVhJQ08iLCB0aWZmZXMpXQojYV9maWxlcyA8LSBhX2ZpbGVzWzJdCnNlcnZfMSA8LSBsYXBwbHkoYV9maWxlcywgcmFzdCkKdGYgPC0gYmFzZW5hbWUoYV9maWxlcykKdGVtcCA8LSB0cmltKHByb2plY3Qoc2Vydiwgc2Vydl8xW1sxXV0pKQpzZXJ2XzEgPC0gbGFwcGx5KHNlcnZfMSwgZnVuY3Rpb24ocil7CiAgciA8LSBjcm9wKHIsdGVtcCwgc25hcD0gImluIiwgZXh0ZW5kPVRSVUUpCiAgaWYgKCFjb21wYXJlR2VvbShyLCB0ZW1wLCBzdG9wT25FcnJvciA9IEZBTFNFKSkgewogICAgICBtZXNzYWdlKCJBbGlnbmluZyByYXN0ZXI6ICIsIG5hbWVzKHIpKQogICAgICAjIFJlc2FtcGxlIHRvIGFsaWduIHdpdGggdGhlIHRlbXBsYXRlCiAgICAgIHJlc2FtcGxlKHIsIHRlbXAsIG1ldGhvZCA9ICJiaWxpbmVhciIpCiAgICB9IGVsc2UgewogICAgICAjIFJldHVybiByYXN0ZXIgYXMgaXMgaWYgYWxyZWFkeSBhbGlnbmVkCiAgICAgIG1lc3NhZ2UoIlJhc3RlciBhbHJlYWR5IGFsaWduZWQ6ICIsIG5hbWVzKHIpKQogICAgICByCiAgICB9CiAgciA8LSB0cmltKHIpCiAgI3IgPC0gbWFzayhyLHRlbXApCnIgPC0gcHJvamVjdChyLCBzZXJ2LCBtZXRob2QgPSAnYmlsaW5lYXInKQp9KQoKc2Vydl8xIDwtIGxhcHBseShzZXJ2XzEsIGZ1bmN0aW9uKHIpewogIHIgPC0gbWFzayhyLHNlcnYpCn0pCgptYXAoMTpsZW5ndGgoc2Vydl8xKSwgZnVuY3Rpb24oeCkgd3JpdGVSYXN0ZXIoc2Vydl8xW1t4XV0sIHBhc3RlMChoZXJlKCJJbnRlcnZlbnRpb25zIiwgIk1leF9pbnRlcnZlbnRpb24iKSwgJy8nLCB0Zlt4XSksIG92ZXJ3cml0ZT1UUlVFKSkKc2Vydl8xIDwtIGxhcHBseSh0aWZmZXMsIHJhc3QpCnNlcnZfMSA8LSAoZG8uY2FsbChjLHNlcnZfMSkpCnNlcnZfMSA8LSB0cmltKG1lcmdlKHNlcnZfMSxzZXJ2KSkgI2FkZCBiYWNrZ3JvdW5kIG9mIFplcm9zCndyaXRlUmFzdGVyKHNlcnZfMSwgcGFzdGUwKGhlcmUoIkludGVydmVudGlvbnMiLCAiTWV4X2ludGVydmVudGlvbiIpLCcvJywgJ3NlcnZfTUVYSUNPLnRpZicpLCBvdmVyd3JpdGU9VFJVRSkKYGBgCgojIyMgNC4xLjIgUnVuIFNhbXBsaW5nIGFuZCBTeW50aGV0aXplIHJlc3VsdHMgLSBZdWNhdGFuCgpgYGB7ciBzYW1wbGluZyB0YXJnZSBhcmVhIE1YLCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQojc2Vydl8xIDwtIHJhc3QoaGVyZSgiSW50ZXJ2ZW50aW9ucyIsICJNZXhfaW50ZXJ2ZW50aW9uIiwnLycsICdzZXJ2X01FWElDTy50aWYnKSkKcmVzdF9tIDwtIHJhc3QoaGVyZSgnSW50ZXJ2ZW50aW9ucycsICdNZXhfaW50ZXJ2ZW50aW9uJywgJ01leF9ncmlzY29tLnRpZicpKQpyY2wgPC0gbWF0cml4KGMoCiAgLUluZiwgMCwgMCwgICMgQW55IHZhbHVlIGZyb20gLUluZmluaXR5IHRvIDAgcmVtYWlucyAwCiAgMCwgSW5mLCAxICAgIyBBbnkgdmFsdWUgZnJvbSAwIHRvIEluZmluaXR5IGJlY29tZXMgMQopLCBuY29sID0gMywgYnlyb3cgPSBUUlVFKQpyZXN0X20gPC0gY2xhc3NpZnkocmVzdF9tLCByY2wpCgpyZXN0X20gPC1wcm9qZWN0KHJlc3RfbSwgc2Vydl8xKQpyZXN0X20gPC0gdGVycmE6OnJlc2FtcGxlKHJlc3RfbSwgc2Vydl8xKQpzZXJ2XzEgPC0gbWFzayhzZXJ2XzEscmVzdF9tLCBtYXNrdmFsdWVzPTApCiMgQ2FsY3VsYXRlIHRoZSBudW1iZXIgb2YgcGl4ZWxzIG5lZWRlZCBmb3IgMTUsMDAwIGhlY3RhcmVzCnBpeGVsX2FyZWEgPC0gMzAgKiAzMCAgIyBBcmVhIG9mIGEgc2luZ2xlIHBpeGVsIGluIHNxdWFyZSBtZXRlcnMgKDMwbSByZXNvbHV0aW9uKQpoZWN0YXJlX2FyZWEgPC0gMTAwMDAgICMgQXJlYSBvZiBvbmUgaGVjdGFyZSBpbiBzcXVhcmUgbWV0ZXJzCnBpeGVsc19uZWVkZWQgPC0gcm91bmQoKDE1MDAwICogaGVjdGFyZV9hcmVhKSAvIHBpeGVsX2FyZWEpCgojIE51bWJlciBvZiByZXBldGl0aW9ucwpuX3JlcGV0aXRpb25zIDwtIDMwCiMgRnVuY3Rpb24gdG8gcGVyZm9ybSB0aGUgc2FtcGxpbmcgYW5kIGNhbGN1bGF0aW9ucwpzYW1wbGVfYW5kX2NhbGN1bGF0ZSA8LSBmdW5jdGlvbihpLCByYXN0ZXIsIHBpeGVsc19uZWVkZWQpIHsKICAjIFNhbXBsZSBwaXhlbHMgYW5kIGRpcmVjdGx5IGV4dHJhY3QgdmFsdWVzICh3aXRob3V0IG5hLnJtKQogIHNhbXBsZV92YWx1ZXMgPC0gc3BhdFNhbXBsZShyYXN0ZXIsIHNpemUgPSBwaXhlbHNfbmVlZGVkLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gInJhbmRvbSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYS5ybSA9IEZBTFNFLCAgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzLnBvaW50cyA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeHkgPSBGQUxTRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gVFJVRSkgCgogICMgUmVtb3ZlIHJvd3Mgd2hlcmUgQUxMIHZhbHVlcyBhcmUgTkEKICBzYW1wbGVfdmFsdWVzIDwtIHNhbXBsZV92YWx1ZXNbcm93U3Vtcyhpcy5uYShzYW1wbGVfdmFsdWVzKSkgIT0gbmNvbChzYW1wbGVfdmFsdWVzKSwgXQoKICAjIElmIG5vdCBlbm91Z2ggc2FtcGxlcyBhZnRlciByZW1vdmluZyBOQXMsIHJlc2FtcGxlCiAgaWYgKG5yb3coc2FtcGxlX3ZhbHVlcykgPCBwaXhlbHNfbmVlZGVkKSB7CiAgICBzYW1wbGVfdmFsdWVzIDwtIHJiaW5kKAogICAgICBzYW1wbGVfdmFsdWVzLAogICAgICBzcGF0U2FtcGxlKHJhc3Rlciwgc2l6ZSA9IHBpeGVsc19uZWVkZWQgLSBucm93KHNhbXBsZV92YWx1ZXMpLAogICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJyYW5kb20iLCBuYS5ybSA9IFRSVUUsIAogICAgICAgICAgICAgICAgIGFzLnBvaW50cyA9IEZBTFNFLCB4eSA9IEZBTFNFLCB2YWx1ZXMgPSBUUlVFKQogICAgKQogIH0KCiAgIyBDYWxjdWxhdGUgc3VtbWFyeSBzdGF0aXN0aWNzCiAgYmFuZF9zdGF0cyA8LSBhcHBseShzYW1wbGVfdmFsdWVzLCAyLCBmdW5jdGlvbih4KSB7IAogICAgbWVhbl92YWwgPC0gbWVhbih4KQogICAgc2RfdmFsIDwtIHNkKHgpCiAgICBuX3ZhbCA8LSBsZW5ndGgoeCkKICAgIHNlX3ZhbCA8LSBzZF92YWwgLyBzcXJ0KG5fdmFsKQogICAgbWFyZ2luX2Vycm9yIDwtIHF0KDAuOTc1LCBkZiA9IG5fdmFsIC0gMSkgKiBzZV92YWwKICAgIGxvd2VyX2NpIDwtIG1lYW5fdmFsIC0gbWFyZ2luX2Vycm9yCiAgICB1cHBlcl9jaSA8LSBtZWFuX3ZhbCArIG1hcmdpbl9lcnJvcgogICAgcmV0dXJuKGMobWVhbiA9IG1lYW5fdmFsLCBsb3dlcl9jaSA9IGxvd2VyX2NpLCB1cHBlcl9jaSA9IHVwcGVyX2NpKSkKICB9KQoKICBiYW5kX3N0YXRzX2RmIDwtIGFzLmRhdGEuZnJhbWUodChiYW5kX3N0YXRzKSkKICBiYW5kX3N0YXRzX2RmJHJlcGV0aXRpb24gPC0gaQoKICAjIENhbGN1bGF0ZSBzdW0gb2YgcGl4ZWwgdmFsdWVzIGZvciBlYWNoIGJhbmQKICBiYW5kX3N1bXMgPC0gY29sU3VtcyhzYW1wbGVfdmFsdWVzKSAKICBiYW5kX3N0YXRzX2RmJHN1bSA8LSBiYW5kX3N1bXMKCiAgcmV0dXJuKGJhbmRfc3RhdHNfZGYpCn0KCiMgVXNpbmcgbWNsYXBwbHkgKHBhcmFsbGVsIHByb2Nlc3NpbmcpCm51bV9jb3JlcyA8LSAxNSAKcmVzdWx0c19saXN0IDwtIG1jbGFwcGx5KDE6bl9yZXBldGl0aW9ucywgc2FtcGxlX2FuZF9jYWxjdWxhdGUsIAogICAgICAgICAgICAgICAgICAgICAgICAgcmFzdGVyID0gc2Vydl8xLCAKICAgICAgICAgICAgICAgICAgICAgICAgIHBpeGVsc19uZWVkZWQgPSBwaXhlbHNfbmVlZGVkLAogICAgICAgICAgICAgICAgICAgICAgICAgbWMuY29yZXMgPSBudW1fY29yZXMpIAoKcmVzdWx0c19saXN0IDwtIGxhcHBseShyZXN1bHRzX2xpc3QsIGZ1bmN0aW9uKGRmKXsKICBkZiA8LSBkZiAlPiUgbXV0YXRlKGJhbmQ9cm93bmFtZXMoZGYpKQp9KQojIENvbWJpbmUgYWxsIHJlc3VsdHMgaW50byBhIHNpbmdsZSBkYXRhIGZyYW1lCmFsbF9yZXN1bHRzIDwtIGFzX3RpYmJsZShkby5jYWxsKHJiaW5kLCByZXN1bHRzX2xpc3QpKQoKCiMgQWRkIG5ldyBjb2x1bW5zIHdpdGggdGhlIHNlcnZpY2UgbmFtZXMgYW5kIHVuaXRzLgphbGxfcmVzdWx0cyA8LSBhbGxfcmVzdWx0cyAlPiUKICBtdXRhdGUoU2VydmljZSA9IGNhc2Vfd2hlbigKICAgIGJhbmQgPT0gImN2X2hhYml0YXRfdmFsdWVfU2MzdjEtRVNBbW9kMl92Ml9tZDVfNjQwODJiIiB+ICJDb2FzdGFsIFByb3RlY3Rpb24iLAogICAgYmFuZCA9PSAibmF0dXJlX2FjY2Vzc19kaWZmX1NjM3YxX1BOVm5vYWctZXNhMjAyMCIgfiAiTmF0dXJlIEFjY2VzcyIsCiAgICBiYW5kID09ICJuaXRyb2dlbl9FU0Ftb2QyLVNjM3YxX21kNV8wMjRhMzYiIH4gIk5pdHJvZ2VuIEV4cG9ydCIsCiAgICBiYW5kID09ICJwb2xsaW5hdGlvbl9wcGxfZmVkX29uX2FnXzEwc19TYzN2MV9QTlZub2FnLWVzYTIwMjBfbWQ1XzQwNWM4OCIgfiAiUG9sbGluYXRpb24iLAogICAgYmFuZCA9PSAicG9sbGluYXRpb25fcHBsX2ZlZF9vbl9oYWJfU2MzdjFfUE5WX25vX2FnLUVTQV9tZDVfNTc2NzkwIiB+ICJQb2xsaW5hdGlvbiAocGVvcGxlIGZlZCBvbiBIYWIpIiwKICAgIGJhbmQgPT0gInNlZGltZW50X0VTQW1vZDItU2MzdjFfbWQ1XzE0OTA3OCIgfiAiU2VkaW1lbnQgRXhwb3J0IiwKICAgICMgLi4uIGFkZCBtb3JlIGNhc2VzIGZvciBvdGhlciBiYW5kcyAuLi4KICAgIFRSVUUgfiBiYW5kICAjIEtlZXAgdGhlIG9yaWdpbmFsIGJhbmQgbmFtZSBpZiBubyBtYXRjaAogICkpCgphbGxfcmVzdWx0cyA8LSBhbGxfcmVzdWx0cyAlPiUKICBtdXRhdGUodW5pdHMgPSBjYXNlX3doZW4oCiAgICBiYW5kID09ICJjdl9oYWJpdGF0X3ZhbHVlX1NjM3YxLUVTQW1vZDJfdjJfbWQ1XzY0MDgyYiIgfiAiUmlzayBSZWR1Y3Rpb24gSW5kZXgiLAogICAgYmFuZCA9PSAibmF0dXJlX2FjY2Vzc19kaWZmX1NjM3YxX1BOVm5vYWctZXNhMjAyMCIgfiAiUGVvcGxlIHdpdGhpbiAxIGhvdXIiLAogICAgYmFuZCA9PSAibml0cm9nZW5fRVNBbW9kMi1TYzN2MV9tZDVfMDI0YTM2IiB+ICJOaXRyb2dlbiBFeHBvcnQgKGtnL2hhL3llYXIpIiwKICAgIGJhbmQgPT0gInBvbGxpbmF0aW9uX3BwbF9mZWRfb25fYWdfMTBzX1NjM3YxX1BOVm5vYWctZXNhMjAyMF9tZDVfNDA1Yzg4IiB+ICJQb2xsaW5hdGlvbiAoZXF1aXZhbGVudCBwZW9wbGUgZmVkKSIsCiAgICBiYW5kID09ICJwb2xsaW5hdGlvbl9wcGxfZmVkX29uX2hhYl9TYzN2MV9QTlZfbm9fYWctRVNBX21kNV81NzY3OTAiIH4gIlBvbGxpbmF0aW9uIChwZW9wbGUgZmVkIG9uIGhhYikiLAogICAgYmFuZCA9PSAic2VkaW1lbnRfRVNBbW9kMi1TYzN2MV9tZDVfMTQ5MDc4IiB+ICJTZWRpbWVudCBFeHBvcnQgKHRvbi9rZy95ZWFyKSIsCiAgICAjIC4uLiBhZGQgbW9yZSBjYXNlcyBmb3Igb3RoZXIgYmFuZHMgLi4uCiAgICBUUlVFIH4gYmFuZCAgIyBLZWVwIHRoZSBvcmlnaW5hbCBiYW5kIG5hbWUgaWYgbm8gbWF0Y2gKICApKQoKYWxsX3Jlc3VsdHMgPC0gYWxsX3Jlc3VsdHMgJT4lCiAgbXV0YXRlKGNvbG9yID0gY2FzZV93aGVuKAogICAgYmFuZCA9PSAiY3ZfaGFiaXRhdF92YWx1ZV9TYzN2MS1FU0Ftb2QyX3YyX21kNV82NDA4MmIiIH4gIiM3YTAxNzciLAogICAgYmFuZCA9PSAibmF0dXJlX2FjY2Vzc19kaWZmX1NjM3YxX1BOVm5vYWctZXNhMjAyMCIgfiAiI0E1N0MwMCIsCiAgICBiYW5kID09ICJuaXRyb2dlbl9FU0Ftb2QyLVNjM3YxX21kNV8wMjRhMzYiIH4gIiMyYzk0NGMiLAogICAgYmFuZCA9PSAicG9sbGluYXRpb25fcHBsX2ZlZF9vbl9hZ18xMHNfU2MzdjFfUE5Wbm9hZy1lc2EyMDIwX21kNV80MDVjODgiIH4gIiNkZDFjNzciLAogICAgYmFuZCA9PSAicG9sbGluYXRpb25fcHBsX2ZlZF9vbl9oYWJfU2MzdjFfUE5WX25vX2FnLUVTQV9tZDVfNTc2NzkwIiB+ICIjZGQxYjU2IiwKICAgIGJhbmQgPT0gInNlZGltZW50X0VTQW1vZDItU2MzdjFfbWQ1XzE0OTA3OCIgfiAiIzA4MzA2YiIsCiAgICAjIC4uLiBhZGQgbW9yZSBjYXNlcyBmb3Igb3RoZXIgYmFuZHMgLi4uCiAgICBUUlVFIH4gYmFuZCAgIyBLZWVwIHRoZSBvcmlnaW5hbCBiYW5kIG5hbWUgaWYgbm8gbWF0Y2gKICApKQoKc2F2ZShhbGxfcmVzdWx0cywgZmlsZT1oZXJlKCJJbnRlcnZlbnRpb25zIiwgIk1leF9pbnRlcnZlbnRpb24iLCAiYWxsX3Jlc3VsdHNfbXguUkRhdGEiKSkgCmBgYAoKIyMjIDQuMS4zIC4gUGxvdCBSZXN1bHRzIFl1Y2F0YW4gCgpgYGB7ciBwbG90IHl1Y2F0YW4sIGVjaG89RkFMU0V9CmxvYWQoZmlsZT1oZXJlKCJJbnRlcnZlbnRpb25zIiwgIk1leF9pbnRlcnZlbnRpb24iLCAiYWxsX3Jlc3VsdHNfbXguUkRhdGEiKSkKZGYgPC1hbGxfcmVzdWx0cyAlPiUgIGZpbHRlcihiYW5kIT0ibmF0dXJlX2FjY2Vzc19kaWZmX1NjM3YxX1BOVm5vYWctZXNhMjAyMCIpICU+JSBmaWx0ZXIoYmFuZCE9ICJwb2xsaW5hdGlvbl9wcGxfZmVkX29uX2hhYl9TYzN2MV9QTlZfbm9fYWctRVNBX21kNV81NzY3OTAiKQojIEFzc3VtaW5nIHlvdXIgJ2FsbF9yZXN1bHRzJyBkYXRhIGZyYW1lIGhhcyB0aGUgY29sdW1ucyAnU2VydmljZScsICd1bml0cycsIGFuZCAnY29sb3InCiMgQXNzdW1pbmcgeW91ciAnYWxsX3Jlc3VsdHMnIGRhdGEgZnJhbWUgaGFzIHRoZSBjb2x1bW5zICdTZXJ2aWNlJywgJ3VuaXRzJywgYW5kICdjb2xvcicKCiMgR2VuZXJhdGUgdGhlIGdncGxvdCBvYmplY3QKcGxvdCA8LSBnZ3Bsb3QoZGYsIGFlcyh5ID0gc3VtLCBmaWxsID0gY29sb3IpKSArCiAgZ2VvbV9ib3hwbG90KCkgKwogIGxhYnModGl0bGUgPSBzdHJfd3JhcCgiVG90YWwgZXN0aW1hdGVkIHNlcnZpY2UgY2hhbmdlIGluIHVuaXRzIGZvciB0aGUgdGFyZ2V0IGludGVydmVudGlvbiBhcmVhIC0gWXVjYXRhbiIsIHdpZHRoID0gNTApLCAKICAgICAgIHkgPSAiVG90YWwgU3VtIFZhbHVlIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKAogICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpY2tzLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLAogICAgc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChmYWNlID0gImJvbGQiKSwKICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIiAgIyBSZW1vdmUgbGVnZW5kIHNpbmNlIGNvbG9yIGlzIGFscmVhZHkgbWFwcGVkCiAgKSArCiAgc2NhbGVfZmlsbF9pZGVudGl0eSgpICsgCiAgZmFjZXRfd3JhcCh+IFNlcnZpY2UsIHNjYWxlcyA9ICJmcmVlX3kiLCBsYWJlbGxlciA9IGxhYmVsbGVyKFNlcnZpY2UgPSBsYWJlbF93cmFwX2dlbih3aWR0aCA9IDEwKSkpICsgIAogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBmdW5jdGlvbih4KSB7CiAgICBpZiAobWF4KHgsIG5hLnJtID0gVFJVRSkgPiAxMDAwMDApIHsKICAgICAgcGFzdGUwKGZvcm1hdCh4IC8gMTAwMCwgYmlnLm1hcmsgPSAiLiIsIGRlY2ltYWwubWFyayA9ICIsIiksICJrIikKICAgIH0gZWxzZSB7CiAgICAgIGZvcm1hdCh4LCBiaWcubWFyayA9ICIuIiwgZGVjaW1hbC5tYXJrID0gIiwiKQogICAgfQogIH0pIApwcmludChwbG90KQpgYGAKCgojIE5leHQgU3RlcHM6CgpSdW4gdGhlIEFuYWx5c2lzIGZvciBNYWRyZSBkZSBEaW9zLCBpbmNvcnBwb3JhdGUgYmVuZWZpY2lhcmllcy9wb3B1bGF0aW9uIHJlbGF0ZWQgZGF0YSwgYXMgdGhlIHRhcmdldCBtZXRyaWMgaXMgbm90IHRoZSBzdW0gb2YgdGhlIHZhbHVlcy4KCg==